【问题标题】:How to log SQL statements in Grails如何在 Grails 中记录 SQL 语句
【发布时间】:2011-02-03 20:09:54
【问题描述】:

我想在控制台或文件中登录 Grails 执行的所有查询,以检查性能。

我已经配置了this,但没有成功。

任何想法都会有所帮助。

【问题讨论】:

  • 所提供的解决方案都不适合我。我写这篇文章只是为了让大家知道我有多绝望。

标签: sql logging grails


【解决方案1】:

设置

datasource {
...
logSql = true
}

DataSource.groovy 中(根据these 指令)足以让它在我的环境中工作。似乎部分常见问题解答已过时(例如多对多列倒退问题),因此这也可能在此期间发生了变化。

【讨论】:

  • logSql=true 单独是不够的。也必须打开休眠日志记录。请参阅@Pete 的回答。
  • 我注意到这不包括 SQL 语句中“?”所在的值。
  • 这可行,但适用于所有查询。是否也可以为特定条件打印生成的 sql 而无需设置 logSql=true ?
  • @Guus 如何打印为特定条件生成的 sql?
  • @biniam_Ethiopia 据我所知,这是不可能的。我想要这个,而且调试某些类很烦人,也不想看到其他查询。
【解决方案2】:

我发现执行以下操作更有用,即启用 Hibernate 的日志记录以记录 SQL 以及绑定变量(这样您就可以看到传递到调用中的值,并轻松地在编辑器中复制 SQL 或其他方式) .

在您的 Config.groovy 中,将以下内容添加到您的 log4j 块中:

log4j = {

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

【讨论】:

  • 这个我用过很多次了。需要注意的一件事:输出参数非常昂贵。我建议只在你的开发盒上这样做。
  • 您还可以将format_sql = true 添加到您的DataSource.groovyhibernate 块中,以获得格式良好的输出。
  • 注意:这将记录从查询结果集中提取的 where 子句参数和列值。要仅记录 where 子句参数,请使用 trace 'org.hibernate.type.BasicBinder'
  • 有人知道 grails 3.3.8 的等价物吗?
  • 由于某种原因,语法上无效的查询(很遗憾,由 Hibernate 自己生成!)不会被记录 - 所有其他查询都会被记录...可能是 Hibernate 本身的问题?
【解决方案3】:

对于 grails 3.*

选项 #1 将以下内容添加到 logback.groovy

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

选项 #2 将以下内容添加到 application.yml 中的 dataSource。但是这种方法不会记录参数值

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

【讨论】:

    【解决方案4】:

    试试这个:

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

    它避免了跟踪记录 Hibernate type 包的性能问题。这适用于 Hibernate 3.6 及更高版本。我来自:https://burtbeckwith.com/blog/?p=1604

    【讨论】:

      【解决方案5】:

      解决方案仅用于开发,不适用于生产。

      以上所有答案都有效且正确。但是它们并没有以一种很好的人类可读方式显示完整的查询。如果想查看最终(没有任何?、?)查询,您有两种选择。

      A) 使用 log4jdbc 或 p6Spy 代理您的 jdbc 连接。

      B) 在数据库级别查看它。比如用mysql真的很容易做到。

      找出您的 general_log_file 在哪里。如果尚未激活,则激活常规日志。

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

      现在所有内容都记录到您的日志文件中。 Mac / linux 示例以显示您的查询流。

      tail -f path_to_log_file 
      

      【讨论】:

        【解决方案6】:

        下一个对我有用:

        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
        // ...
        

        来源:http://sergiodelamo.es/log-sql-grails-3-app/

        【讨论】:

          【解决方案7】:

          仅供参考,但我使用 p6spy 记录 SQL 查询。它是一个小型的中间 jdbc 驱动程序。将记录确切的查询,因为它将被发送到服务器(包括参数)。

          将它包含在您的项目中:

          runtime 'p6spy:p6spy:3.0.0'
          

          更改您的数据源驱动程序:

          driverClassName: com.p6spy.engine.spy.P6SpyDriver
          

          还有你的 jdbc url:

          url: jdbc:p6spy:mysql://
          

          使用 spy.properties(在 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
          

          不要忘记在生产中禁用它!

          【讨论】:

            【解决方案8】:

            我知道很久以前就有人问过这个问题并得到了回答。但我只是碰巧看到了这个问题,无法阻止自己在我们的项目中回答或分享我们的 sql 日志记录实现方法。 希望对您有所帮助。

            目前它处于开发环境中。 我们正在使用“log4jdbc Driver Spy”来记录 sql。

            配置:

            在您的 BuildConfig.groovy 中: 添加以下依赖项:

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

            并且在您的 DataSource 或其他相关配置中:[无论您在哪里定义了与数据源相关的配置], 添加:

            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'
            
            }
            

            根据我的个人经验,我发现它在调试时非常有用和有帮助。 您还可以在此站点中找到更多信息。 https://code.google.com/p/log4jdbc-remix/

            国王的问候

            【讨论】:

              【解决方案9】:

              如果您安装了console 插件,您可以使用这个小代码 sn-p 获取 sql 日志记录。

              // 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
              }
              

              这是上述许多解决方案的变体,但允许您在运行时调整值。就像处理logToStdout 的其他解决方案一样,它只显示查询而不是绑定值。

              这个想法是从我几年前读过的一篇 burtbeckwith 帖子中偷来的,我现在找不到了。它已被编辑为与 grails 3.3 一起使用。

              可以使用类似的技术来打开特定集成测试的日志记录:

              class SomeIntegrationSpec extends IntegrationSpec {
              
                  def sessionFactory
              
                  def setup() {
                      sessionFactory.settings.sqlStatementLogger.logToStdout = true
                  }
              
                  def cleanup() {
                      sessionFactory.settings.sqlStatementLogger.logToStdout = false
                  }
              
                  void "some test"() {
                         ...
                  }
              

              这将为这个文件中的测试打开 sql 日志记录。

              【讨论】:

                【解决方案10】:

                对于特定的代码块,我们还可以创建一个接受闭包的方法。例如。

                 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")}
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2018-06-19
                  • 2019-04-01
                  • 2011-07-08
                  • 1970-01-01
                  • 1970-01-01
                  • 2017-04-07
                  • 1970-01-01
                  相关资源
                  最近更新 更多