在使用hibernate的getHibernateTemplate()时怎么让控制台输出封装好的SQL? 怎么用日志打印出来?

我们在使用 Hibernate 时一般只会关注是否显示生成的 SQL 语句,不过有些时候还不够。默认时 Hibernate 执行的 SQL 语句是打印在控制台上的,它也可以配置为输出给 Log4J 或是 Log4Back,还能显示出更详细的参数和取值信息。这里简单讲来。

Hibernate 的配置文件 hibernate.cfg.xml 里提供有三个有关显示 SQL 的配置项,如果是与 Spring 联合,也可以配置到 Spring 的配置中。它们的取值是 boolean 值。

  • 1) hibernate.show_sql - 是否显示所生成 SQL 语句,我们最常和它打交道
  • 2) hibernate.format_sql - 是否格式化生成的 SQL 语句,增加可读性,不然全挤在一行
  • 3) hibernate.use_sql_comments - 是否显示注释,用以指出什么操作产生的 SQL 语句,相比上面两条而言,这个配置会稍稍陌生些

来看看加了上面三条配置后产生的效果,执行了 Hibernate 查询后,在控制台上产生如下输出:

Hibernate:
     /* load collection cc.unmi.test.model.Post.securities */ select
         securities0_.post_id as post1_7_1_,
         security1_.shareclassid as sharecla1_16_0_,
         security1_.company_id as company2_16_0_,
     from
         Post_Security_Relationship securities0_
     inner join
         unmi.securities security1_
             on securities0_.shareclassid=security1_.shareclassid
     where
         securities0_.post_id=?

hibernate.show_sql 控制全局是否显示生成的 SQL 语句,hibernate.format_sql 格式化后的效果如上,不然就是一行,而 hibernate.use_sql_comments 输出的是红色的部分,表明是在加哉 securities 集合时所执行的 SQL 语句。

Hibernate 默认是把 SQL 语句是输出到控制台,而控制台中的内容查阅起来并不方便,例如超过控制台缓存的内容会被清掉,不是谁都能看到控制台,难以与时间关联起来。虽然有些应用服务器会把控制台输出重定向到文件,但总没有 Log4J 或 Slf4J 那样的专业日志工具来得便捷。

因为 Hibernate 在输出 SQL 时使用的 logger 名为 org.hibernate.SQL, 所以想要让 SQL 语句输出到 Log4J 或是 Slf4J 日志中(日志文件或是记在别处,由 Appender 决定的),只要在 log4j.properties(log4j.xml 参考相应配置) 中加上:

log4j.logger.org.hibernate.SQL=DEBUG

记得同时把 Hibernate 配置文件中(或者 Spring 中关于 Hibernate 的配置中) 的 hibernate.show_sql 设置为 false,不然可能在控制台下会有双份输出(Log4J 配置了 ConsoleAppender 时)。

如果就用的是 Log4Back 的话,就在 Log4Back 的配置文件 log4back.xml 中加上:

<logger name="org.hibernate.SQL" level="DEBUG"/>

这时的日志输出格式与控制台下没多少分别,只是跟着 Log4J 或 Slf4J 跑而已,像:

20:13:40.757 [http-8080-1] DEBUG org.hibernate.SQL -
     /* load collection cc.unmi.test.model.Post.tags */ select
         tags0_.post_id as post1_7_1_,
         tags0_.tag_id as tag2_1_,
         elementite1_.id as id3_0_,
     from
         Post_Tag_Relationship tags0_
     inner join
         unmi.element_item elementite1_
             on tags0_.tag_id=elementite1_.id
     where
         tags0_.post_id=?

只有红色部分不同,应用上了 Log4J 或 Slf4J 的配置了,可以看到执行的时间、线程等相关信息。

我们想知道前面输出的 SQL 语句中的 ? 参数代表的实际值是什么,还需要打开一个日志 org.hibernate.type.descriptor.sql.BasicBinder 的输出级别为 TRACE,这里同时把 org.hibernate.type.descriptor.sql.BasicExtractor 的输出级别也设置为 TRACE,来看看效果:

log4j.properties 中配置为:

log4j.logger.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
 log4j. loggerorg.hibernate.type.descriptor.sql.BasicExtractor=TRACE

logback.xml 中配置为:

<logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE"/>
 <logger name="org.hibernate.type.descriptor.sql.BasicExtractor" level="TRACE"/>

之后看输出:

20:13:40.710 [http-8080-1] DEBUG org.hibernate.SQL -
     /* load collection cc.unmi.test.model.Post.categories */ select
         categories0_.post_id as post1_7_1_,
         elementite1_.id as id3_0_,
     from
         Post_Category_Relationship categories0_
     inner join
         unmi.element_item elementite1_
             on categories0_.category_id=elementite1_.id
     where
         categories0_.post_id=?
 20:13:40.710 [http-8080-1] TRACE org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [1] as [INTEGER] - 10
 20:13:40.710 [http-8080-1] TRACE org.hibernate.type.descriptor.sql.BasicExtractor - found [1002] as column [id3_0_]
 20:13:40.710 [http-8080-1] TRACE org.hibernate.type.descriptor.sql.BasicExtractor - found [10] as column [post1_7_1_]

红色部分是 org.hibernate.type.descriptor.sql.BasicBinder=TRACE 控制的,显示了绑定给 SQL 的参数列表。蓝色部分是 org.hibernate.type.descriptor.sql.BasicExtractor=TRACE 控制的,显示了查询后记录的字段值。注意这两个属性是要设置到 TRACE 级别,所以在一般日志的全局 DEBUG 级别之下,它们会表示不受影响。

有时候想要显示查询中命名参数的值,用 :email 而不是 ? 的形式,则还需要引入两个

log4j.logger.org.hibernate.engine.QueryParameters=DEBUG

log4j.logger.org.hibernate.engine.query.HQLQueryPlan=DEBUG

效果是这样的:

20:13:40.710 [http-8080-1] org.hibernate.engine.query.HQLQueryPlan - find: from User where email = :email
 20:13:40.710 [http-8080-1] org.hibernate.engine.QueryParameters - named parameters: {email=[email protected]}
 20:13:40.726 [http-8080-1] org.hibernate.SQL -
     /* named HQL query findUserByEmail */ select
         user0_.id as id0_,
         user0_.email as email0_,
         user0_.enabled as enabled0_,
         user0_.encodedPassword as encodedP8_0_
     from
         User user0_
     where
         user0_.email=?

对上面综合一下,比较好的配置可以参考:

hibernate.cfg.xml 中配置:

<property name="hibernate.show_sql">false</property>
<property name="hibernate.format_sql">true</property>
<property name="hibernate.use_sql_comments">true</property>

或者是在 Spring 中关于 Hibernate 的配置属性:

<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.use_sql_comments">true</prop>

而在日志配置中,如 log4j.properties 中配置:

log4j.logger.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
log4j.logger.org.hibernate.type.descriptor.sql.BasicExtractor=TRACE
log4j.logger.org.hibernate.SQL=DEBUG
log4j.logger.org.hibernate.engine.QueryParameters=DEBUG
log4j.logger.org.hibernate.engine.query.HQLQueryPlan=DEBUG

倘若用的是 Slf4J 话,就在 logback.xml 中配置:

<logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE"/>
<logger name="org.hibernate.type.descriptor.sql.BasicExtractor" level="TRACE"/>
<logger name="org.hibernate.SQL" level="DEBUG"/>
<logger name="org.hibernate.engine.QueryParameters" level="DEBUG"/>
<logger name="org.hibernate.engine.query.HQLQueryPlan" level="DEBUG"/>

如果你会觉得日志太多的话,反正我是会这么觉得,那么可考虑把 org.hibernate.type.descriptor.sql.BasicExtractor 设置为 DEBUG,或不设置该配置项

时间: 2024-11-12 23:54:59

在使用hibernate的getHibernateTemplate()时怎么让控制台输出封装好的SQL? 怎么用日志打印出来?的相关文章

加速Java应用开发速度1——加速spring/hibernate应用调试时启动速度

在调试spring应用时,动辄几十秒,甚至有的应用上分钟的启动速度,会让整个调试速度慢下来了.等待时间让人抓狂.不知道大家是如何加速spring应用调试速度的,在此分享下我的一次加速过程.欢迎补充指正. 环境 配置: thinkpad t410 内存:4G内存 CPU:Intel P8700 双核2.53GHZ 系统:WIN XP 开发工具:Intellij IDEA 12.0.4 Maven + spring3.2.3 + hibernate4.2.2+Spring data jpa 1.3.

Hibernate使用注解时的问题

在使用注解进行Hibernate开发时.报了一个如下的错误 Exception in thread "main" org.hibernate.AnnotationException: No identifier specified for entity: com.eyang.hibernate.model.Qygd at org.hibernate.cfg.InheritanceState.determineDefaultAccessType(InheritanceState.java

hibernate 项目启动时总会自动创建表

hibernate 项目启动时总会自动创建表,造成以下错误 Caused by: java.sql.SQLSyntaxErrorException: ORA-00955: 名称已由现有对象使用 经验证,是方言使用错误导致的.项目使用的数据库版本为Oracle11g,方言应该使用  org.hibernate.dialect.Oracle10gDialect 修改配置如下: jpa: show-sql: true database-platform: org.hibernate.dialect.O

SpringMVC 中,当前台传入多个参数时,可将参数封装成一个bean类

在实际业务场景中,当前台通过 url 向后台传送多个参数时,可以将参数封装成一个bean类,在bean类中对各个参数进行非空,默认值等的设置. 前台 url ,想后台传送两个参数,userName 和 password: 1 http://localhost:8082/web/baseAction.do?pathVar=app/task/fetchItemDetail.do?userName=123&password=123 将参数封装成bean 类,并在bean类中对参数进行控制: 1 2 3

eclipse运行 Maven Test命令时控制台输出乱码的解决办法

在Maven的pom.xml文件中增加: <properties>      <argLine>-Dfile.encoding=UTF-8</argLine> </properties> 今天突然遇到这个问题了,上网搜了一下,答案一大堆,还是这个最好!记录一下! eclipse运行 Maven Test命令时控制台输出乱码的解决办法,布布扣,bubuko.com

Maven 执行Javadoc时控制台输出乱码问题

1.0  Maven 执行Javadoc时控制台输出乱码问题 问题描述 最近项目中使用maven-javadoc-plugin生成javadoc时,myEclipse控制台乱码. 插件配置 问题分析 检查maven输出时采用的编码格式 很显然maven默认输出采用GBK编码 myEclipse控制台输出编码,默认采用的是工作空间的编码格式. 改为 结果如下: 来自:http://www.cnblogs.com/albert-sun/archive/2013/03/21/2973993.html

关于上传文件时,提示控制台信息存取失败的解决方法

 如下图所示,用户在上传文件时,提示控制台信息存储失败,无法继续操作. 1.原因分析: ①上传服务异常,可能是数据中心的传服务出现异常 ②查看相关日志,可能的原因,一般是读取加密狗失败,或者服务器IIS未允许ISAPI和CGI限制. 2.根据上述分析,解决方法如下: ①数据中心快速检测:浏览器输入http://IP/viewgood_dcs ②上传服务快速检测:浏览器输入http://IP/viewgood_cdn/1.cdn 总结,在产品正常的使用过程中,难免会遇到各种大大小小的问题,尤其

跟后台打印程序系统服务通讯时出现错误。请打开服务管理单元,确认后台打印程序服务是否在运行。

一: 问题描述: [错误] 事件类型:警告事件来源:TermServDevices事件种类:无事件ID:1114日期:2013-10-16事件:0:06:41用户:N/A计算机:VPS描述:    跟后台打印程序系统服务通讯时出现错误.请打开服务管理单元,确认后台打印程序服务是否在运行.    有关更多信息,请参阅在 http://go.microsoft.com/fwlink/events.asp 的帮助和支持中心.数据: 二:问题原图: 三:解决方法: [解决方法一]    出现这个错误,一

[小技巧]自动化测试时NLog的消息输出到测试结果中

平常我会用Visual Stuido的测试项目,写一些自动化测试,如单元测试.整合测试等等,受测的Code中有很多地方用NLog记录消息,在正试的环境,会写到数据库,但测试时我会想把消息输出到每一个测试的结果中,除了节省数据库外,也比较容易追纵错误消息. 平常我会用Visual Stuido的测试项目,写一些自动化测试,如单元测试.整合测试等等,受测的Code中有很多地方用NLog记录消息,在正试的环境,会写到数据库,但测试时我会想把消息输出到每一个测试的结果中,除了节省数据库外,也比较容易追纵