Cách ghi các câu lệnh SQL trong Grails


86

Tôi muốn đăng nhập bảng điều khiển hoặc trong một tệp, tất cả các truy vấn mà Grails thực hiện, để kiểm tra hiệu suất.

Tôi đã cấu hình điều này mà không thành công.

Bất kỳ ý tưởng sẽ giúp đỡ.


Không có giải pháp nào được cung cấp phù hợp với tôi. Tôi viết thư này chỉ để cho mọi người biết tôi tuyệt vọng như thế nào.
Andrea

Câu trả lời:


131

Cài đặt

datasource {
...
logSql = true
}

trong DataSource.groovy (theo các hướng dẫn này ) là đủ để làm cho nó hoạt động trong môi trường của tôi. Có vẻ như các phần của Câu hỏi thường gặp đã lỗi thời (ví dụ: câu hỏi "từ nhiều cột trở lên") nên đây cũng có thể là điều gì đó đã thay đổi trong thời gian chờ đợi.


6
logSql=truemột mình là không đủ. Ghi nhật ký ngủ đông cũng phải được bật. Hãy xem câu trả lời của @ Pete.
Jason

2
Tôi nhận thấy rằng điều này không bao gồm các giá trị đi trong các câu lệnh SQL có "?".
Jason

1
Điều này hoạt động, nhưng cho tất cả các truy vấn. Cũng có thể in sql được tạo cho một Tiêu chí cụ thể mà không cần phải đặt logSql = true?
Tháng 8

@Guus làm cách nào để in sql đã tạo cho một Tiêu chí cụ thể?
biniam

@biniam_Ethiopia Theo như tôi biết, điều này là không thể. Tôi muốn điều này cũng như nó gây phiền nhiễu cho việc gỡ lỗi các lớp nhất định và không muốn xem các truy vấn khác.
tháng 8

91

Tôi thấy việc làm sau sẽ hữu ích hơn, đó là kích hoạt tính năng ghi nhật ký của Hibernate để ghi lại SQL cùng với các biến liên kết (để bạn có thể thấy các giá trị được truyền vào các cuộc gọi của mình và dễ dàng sao chép SQL trong trình soạn thảo của bạn hoặc bằng cách khác).

Trong của bạn Config.groovy, hãy thêm phần sau vào khối log4j của bạn:

log4j = {

    // Enable Hibernate SQL logging with param values
    trace 'org.hibernate.type'
    debug 'org.hibernate.SQL'
    //the rest of your logging config
    // ...
    }

8
Tôi đã sử dụng điều này nhiều lần. Một điều cần lưu ý: việc xuất các tham số rất đắt. Tôi khuyên bạn chỉ nên làm điều này trên hộp phát triển của bạn.
John Gordon

2
Bạn cũng có thể thêm format_sql = truevào hibernatekhối của bạn DataSource.groovyđể có đầu ra được định dạng độc đáo.
Gregor Petrin

1
Lưu ý: Điều này sẽ ghi lại cả tham số mệnh đề where và giá trị cột được trích xuất từ ​​tập kết quả truy vấn. Để đăng nhập duy nhất mà các thông số điều khoản, sử dụngtrace 'org.hibernate.type.BasicBinder'
GreenGiant

Bất cứ ai biết tương đương cho grails 3.3.8?
John Little

Vì một số lý do, các truy vấn không hợp lệ về cú pháp (được tạo bởi chính Hibernate, thật đáng buồn!) Không được ghi lại - tất cả các truy vấn khác đều được ghi lại ... Có thể là sự cố với chính Hibernate?
Janaka Bandara

32

Đối với grails 3. *

Tùy chọn số 1 thêm phần sau vào logback.groovy

logger("org.hibernate.SQL", DEBUG, ["STDOUT"], false)
logger("org.hibernate.type.descriptor.sql.BasicBinder", TRACE, ["STDOUT"], false)

hoặc là

Tùy chọn # 2 thêm phần sau vào dataSource trong application.yml. Tuy nhiên, cách tiếp cận này không ghi các giá trị tham số

environments:
  local:
    dataSource:
        logSql: true
        formatSql: true

17

Thử đi:

log4j = {
   ...
   debug 'org.hibernate.SQL'
   trace 'org.hibernate.type.descriptor.sql.BasicBinder'
}

Nó tránh các vấn đề về hiệu suất của việc ghi nhật ký theo dõi typegói Hibernate . Điều này hoạt động với Hibernate 3.6 trở lên. Tôi nhận được cái này từ: https://burtbeckwith.com/blog/?p=1604


6

Giải pháp chỉ để phát triển, không phải sản xuất.

Tất cả các câu trả lời trên đều hoạt động và chính xác. Nhưng chúng không hiển thị toàn bộ truy vấn theo cách dễ đọc của con người. Nếu muốn xem truy vấn cuối cùng (không có ?,?), Bạn có hai tùy chọn.

A) proxy kết nối jdbc của bạn với log4jdbc hoặc p6Spy.

B) xem xét nó ở cấp độ cơ sở dữ liệu. Ví dụ thực sự dễ dàng để làm với mysql.

Tìm hiểu vị trí của bạn general_log_file. Nhật ký chung hoạt động nếu chưa được kích hoạt.

mysql command line> show variables like "%general_log%";
mysql command line> set global general_log = true;

Bây giờ mọi thứ đã được ghi vào tệp nhật ký của bạn. Ví dụ về Mac / linux để hiển thị luồng truy vấn của bạn.

tail -f path_to_log_file 

3

Thuần túy chỉ để tham khảo, nhưng tôi sử dụng p6spy để ghi các truy vấn SQL. Đó là một trình điều khiển jdbc trung gian nhỏ. Truy vấn chính xác được ghi lại như nó sẽ được gửi đến máy chủ (có bao gồm các tham số).

đưa nó vào dự án của bạn:

runtime 'p6spy:p6spy:3.0.0'

Thay đổi trình điều khiển nguồn dữ liệu của bạn:

driverClassName: com.p6spy.engine.spy.P6SpyDriver

Và url jdbc của bạn:

url: jdbc:p6spy:mysql://

Định cấu hình nó bằng spy.properties (trong grails-app / conf).

driverlist=org.h2.Driver,com.mysql.jdbc.Driver
autoflush=true
appender=com.p6spy.engine.spy.appender.StdoutLogger
databaseDialectDateFormat=yyyy-MM-dd
logMessageFormat=com.p6spy.engine.spy.appender.MultiLineFormat

Đừng quên tắt tính năng này để sản xuất!


2

Tiếp theo phù hợp với tôi:

grails-app / conf / application.yml

# ...
hibernate:
    format_sql: true # <<<<<<< ADD THIS <<<<<<<
    cache:
        queries: false
        use_second_level_cache: true
# ...
environments:
    development:
        dataSource:
            logSql: true // <<<<<<< ADD THIS <<<<<<<
            dbCreate: create-drop
            url: jdbc:h2:mem:...
# ...

grails-app / conf / logback.groovy

// ...
appender('STDOUT', ConsoleAppender) {
    encoder(PatternLayoutEncoder) {
        pattern = "%level %logger - %msg%n"
    }
}

// >>>>>>> ADD IT >>>>>>>
logger 'org.hibernate.type.descriptor.sql.BasicBinder', TRACE, ['STDOUT']
logger 'org.hibernate.SQL', TRACE, ['STDOUT']
// <<<<<<< ADD IT <<<<<<<

root(ERROR, ['STDOUT'])

def targetDir = BuildSettings.TARGET_DIR
// ...

Nguồn: http://sergiodelamo.es/log-sql-grails-3-app/


1

Tôi biết điều này đã được hỏi và trả lời từ lâu. Nhưng tôi chỉ tình cờ thấy câu hỏi này và không thể ngừng trả lời hoặc chia sẻ phương pháp triển khai ghi nhật ký sql trong dự án của chúng tôi. Hy vọng nó sẽ được một số giúp đỡ.

Hiện tại nó đang trong môi trường phát triển. Chúng tôi đang sử dụng "log4jdbc Driver Spy" để đăng nhập sql.

Cấu hình:

Trong BuildConfig.groovy của bạn: thêm các phần phụ thuộc bên dưới:

dependencies {
.....
runtime 'org.lazyluke:log4jdbc-remix:0.2.7'
}

Và trong DataSource của bạn hoặc cấu hình khác có liên quan: [bất cứ nơi nào bạn đã xác định cấu hình liên quan đến nguồn dữ liệu], Thêm:

datasources{
.....
driverClassName: "net.sf.log4jdbc.DriverSpy",
url: "jdbc:log4jdbc:oracle:thin:@(DESCRIPTION =(ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = XXXXX.XX>XXX)(PORT = 1521))) (CONNECT_DATA = (SID = XXXX)(SERVER =DEDICATED)))",
....
}
log4j = {

    info 'jdbc.sqlonly' //, 'jdbc.resultsettable'

}

Từ kinh nghiệm cá nhân của tôi, tôi thấy nó khá hữu ích và hữu ích trong khi gỡ lỗi. Ngoài ra, bạn có thể tìm thấy thêm thông tin trong trang web này. https://code.google.com/p/log4jdbc-remix/

Trân trọng


0

Đối với một khối mã cụ thể, chúng ta cũng có thể tạo một phương thức chấp nhận một lệnh đóng. ví dụ.

 static def executeBlockAndGenerateSqlLogs(Closure closure) {
    Logger sqlLogger = Logger.getLogger("org.hibernate.SQL");
    Level currentLevel = sqlLogger.level
    sqlLogger.setLevel(Level.TRACE)
    def result = closure.call()
    sqlLogger.setLevel(currentLevel)
    result }

executeBlockAndGenerateSqlLogs{DomainClazz.findByPropertyName("property value")}

0

Nếu bạn đã cài đặt plugin bảng điều khiển , bạn có thể ghi nhật ký sql bằng đoạn mã nhỏ này.

// grails 2.3
def logger=ctx.sessionFactory.settings.sqlStatementLogger

// grails 3.3  
def logger = ctx.sessionFactory.currentSession.jdbcCoordinator.statementPreparer.jdbcService.sqlStatementLogger

logger.logToStdout=true    
try {
   <code that will log sql queries>
}
finally {
    logger.logToStdout = false
}

Đây là một biến thể của nhiều giải pháp ở trên, nhưng cho phép bạn tinh chỉnh giá trị trong thời gian chạy. Và cũng giống như các giải pháp khác xử lý logToStdoutnó chỉ hiển thị các truy vấn chứ không phải các giá trị ràng buộc.

Ý tưởng đã bị đánh cắp từ một bài viết burtbeck với tôi đã đọc cách đây vài năm mà tôi không thể tìm thấy ngay bây giờ. Nó đã được chỉnh sửa để hoạt động với grails 3.3.

Một kỹ thuật tương tự có thể được sử dụng để bật ghi nhật ký cho các thử nghiệm tích hợp cụ thể:

class SomeIntegrationSpec extends IntegrationSpec {

    def sessionFactory

    def setup() {
        sessionFactory.settings.sqlStatementLogger.logToStdout = true
    }

    def cleanup() {
        sessionFactory.settings.sqlStatementLogger.logToStdout = false
    }

    void "some test"() {
           ...
    }

Thao tác này sẽ bật ghi nhật ký sql chỉ cho các bài kiểm tra trong một tệp này.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.