hibernate sql
有两种众所周知的在Grails中记录Hibernate SQL的方法。 一种是在DataSource.groovy
添加logSql = true
(在所有环境或每个环境的顶级块中)
dataSource {
dbCreate = ...
url = ...
...
logSql = true
}
另一种是使用Log4j日志记录配置:
log4j = {
...
debug 'org.hibernate.SQL'
}
logSql
的问题在于它太简单了–它只是将SQL转储到stdout,没有选项可以查看为positional设置的值?
参数。 日志记录方法的可配置性更高,因为您可以根据需要登录控制台,但是可以使用Appender
将日志记录配置到文件,仅用于这些消息的文件或选择的任何目标。
但是日志记录方法也存在问题–通过启用第二个Log4j类别
log4j = {
...
debug 'org.hibernate.SQL'
trace 'org.hibernate.type'
}
我们可以看到变量值,但是对于PreparedStatement
集和 ResultSet
获取都可以看到它们,并且获取可能导致大量的日志文件充满无用的语句。 之所以LongType
,是因为Hibernate用于将Java类值存储和加载到数据库列(例如LongType
, StringType
等)的“ Type”类位于org.hibernate.type
包中,并(间接)扩展了org.hibernate.type.NullableType
它确实记录在其nullSafeSet
和nullSafeGet
方法。
因此,如果您拥有GORM域类
class Person {
String name
}
然后保存一个实例
new Person(name: 'me').save()
您将看到如下输出:
DEBUG hibernate.SQL - insert into person (id, version, name) values (null, ?, ?)
TRACE type.LongType - binding '0' to parameter: 1
TRACE type.StringType - binding 'me' to parameter: 2
DEBUG hibernate.SQL - call identity()
以后运行查询以获取一个或多个实例时
def allPeople = Person.list()
您会看到这样的输出
DEBUG hibernate.SQL - select this_.id as id0_0_, this_.version as version0_0_, this_.name as name0_0_ from person this_
TRACE type.LongType - returning '1' as column: id0_0_
TRACE type.LongType - returning '0' as column: version0_0_
TRACE type.StringType - returning 'me' as column: name0_0_
这对于一个实例来说还不错,但是如果有多个结果,则每个结果都有一个块,每一列都包含一行。
昨天,我在SpringOne 2GX上的Hibernate演讲中谈到了这一点,并意识到应该可以创建一个自定义的Appender
,该Appender
检查这些类的日志语句,而忽略ResultSet
gets产生的语句。 令我惊讶的是,事实证明,在Grails 2.x中,一切都发生了变化,因为我们已从Hibernate 3.3升级到3.6,并且此问题已在Hibernate中得到解决。
上面的输出实际上来自我在2.1.1应用程序中获得意外输出之后创建的1.3.9项目。 这是我在2.1.1中看到的:
DEBUG hibernate.SQL -
/* insert Person
*/ insert
into
person
(id, version, name)
values
(null, ?, ?)
TRACE sql.BasicBinder - binding parameter [1] as [BIGINT] - 0
TRACE sql.BasicBinder - binding parameter [2] as [VARCHAR] - asd
和
DEBUG hibernate.SQL -
/* load Author */ select
author0_.id as id1_0_,
author0_.version as version1_0_,
author0_.name as name1_0_
from
author author0_
where
author0_.id=?
TRACE sql.BasicBinder - binding parameter [1] as [BIGINT] - 1
TRACE sql.BasicExtractor - found [0] as column [version1_0_]
TRACE sql.BasicExtractor - found [asd] as column [name1_0_]
因此,现在不再进行从类型的基类进行的所有日志记录,而是对其进行了重新设计以委托给org.hibernate.type.descriptor.sql.BasicBinder
和org.hibernate.type.descriptor.sql.BasicExtractor
。 很好,因为现在我们可以将Log4j配置更改为
log4j = {
...
debug 'org.hibernate.SQL'
trace 'org.hibernate.type.descriptor.sql.BasicBinder'
}
吃我们的蛋糕也要吃 SQL将记录到可配置的Log4j目标,并且仅记录PreparedStatement
集。
请注意,第二个示例中SQL看起来有所不同,这并不是因为Grails或Hibernate发生了变化,而是因为我始终在测试应用中启用SQL格式设置(带有format_sql
)和注释(带有use_sql_comments
),因此当我启用日志记录时,它最终会变得更多可读性强,我忘了为1.3版应用程序这样做:
hibernate {
cache.use_second_level_cache = true
cache.use_query_cache = false
cache.region.factory_class = 'net.sf.ehcache.hibernate.EhCacheRegionFactory'
format_sql = true
use_sql_comments = true
}
参考:在An Solipsists博客上,从我们的JCG合作伙伴 Burt Beckwith 记录Hibernate SQL 。
翻译自: https://www.javacodegeeks.com/2012/10/logging-hibernate-sql.html
hibernate sql