调试Hibernate生成的SQL

在本文中,我将解释如何调试Hibernate生成的SQL,以便更快地将意外的查询结果跟踪到错误的数据集或查询中的错误。

不再需要呈现Hibernate。 但是,对于那些过去几年住在洞穴中的人来说,Hibernate是两个ORM框架之一(第二个是TopLink),可以极大地简化Java中的数据库访问。

Hibernate的主要目标之一是减少编写的SQL数量,以至于在许多情况下,您甚至都不会编写一行。 但是,很可能有一天,Hibernate的获取机制将无法为您带来预期的结果,而问题将立即开始。 从这一点出发,在进一步研究之前,您应该确定哪个是正确的:

  • 要么初始数据集错误
  • 或生成的查询是
  • 或两者(如果您真的很不幸)

能够快速诊断出真正的原因将为您节省很多时间。 为此,最大的步骤是查看生成的SQL:如果可以在正确的查询工具中执行它,则可以将纯SQL结果与Hibernate的结果进行比较,并确定真正的原因。 有两种查看SQL的解决方案。

11显示SQL

第一个解决方案是最简单的解决方案。 它是Hibernate配置的一部分,并有大量文档记录。 只需将以下行添加到您的hibernate.cfg.xml文件中:

<hibernate-configuration>
  <session-factory>
...
    <propertyname="hibernate.show_sql"> true </property>
  </session-factory>
</hibernate-configuration>

上一片段可能会在日志中显示如下内容:

selectthis_.PER_N_IDasPER1_0_0_,this_.PER_D_BIRTH_DATEasPER2_0_0_,
this_.PER_T_FIRST_NAMEasPER3_0_0_,this_.PER_T_LAST_NAMEasPER4_0_0_fromT_PERSONthis_

可读性不强,但足以复制/粘贴到您喜欢的查询工具中。

这样做的主要缺点是,如果查询具有参数,则它们将显示为?。 并且不会显示其值,如以下输出所示:

selectthis_.PER_N_IDasPER1_0_0_,this_.PER_D_BIRTH_DATEasPER2_0_0_,
this_.PER_T_FIRST_NAMEasPER3_0_0_,this_.PER_T_LAST_NAMEasPER4_0_0_
fromT_PERSONthis_where(this_.PER_D_BIRTH_DATE=?andthis_.PER_T_FIRST_NAME=?andthis_.PER_T_LAST_NAME=?)

如果参数太多,那么您将痛苦不堪,将每个参数替换为其值将花费太多时间。

但是,恕我直言,这种简单的配置应该在所有环境中启用(保存生产),因为可以很容易地将其关闭。

代理驱动

第二种解决方案更具侵入性,涉及第三方产品,但功能更强大。 它包括在JDBC和实际驱动程序之间放置一个代理驱动程序,以便记录所有生成的SQL。 它与所有依赖JDBC /驱动程序体系结构的ORM解决方案兼容。

P6Spy是执行此操作的驱动程序。 尽管它已经很老了(最新版本可以追溯到2003年),但它并不是过时的,可以满足我们的目的。 它由代理驱动程序本身和属性配置文件(spy.properties)组成,两者均应存在于类路径中。

为了利用P6Spy功能,您唯一要做的就是告诉Hibernate使用特定的驱动程序:

<hibernate-configuration>
  <session-factory>
    <!-- Only this line changes -->
    <propertyname="connection.driver_class"> com.p6spy.engine.spy.P6SpyDriver </property>
...
 </session-factory>
</hibernate-configuration>

这是最小的spy.properties:

module.log=com.p6spy.engine.logging.P6LogFactory
realdriver=org.hsqldb.jdbcDriver
autoflush=true
excludecategories=debug,info,batch,result
appender=com.p6spy.engine.logging.appender.StdoutLogger

注意realdriver参数,以便P6Spy知道将调用重定向到哪里。

有了这些,上面的输出变为:

1270906515233|3|0|statement|
  select this_.PER_N_ID as PER1_0_0_, this_.PER_D_BIRTH_DATE as PER2_0_0_,
  this_.PER_T_FIRST_NAME as PER3_0_0_, this_.PER_T_LAST_NAME as PER4_0_0_ from T_PERSON this_ where (
  this_.PER_D_BIRTH_DATE=? and this_.PER_T_FIRST_NAME=? and this_.PER_T_LAST_NAME=?)|
  select this_.PER_N_ID as PER1_0_0_, this_.PER_D_BIRTH_DATE as PER2_0_0_,
  this_.PER_T_FIRST_NAME as PER3_0_0_, this_.PER_T_LAST_NAME as PER4_0_0_ from T_PERSON this_ where (
  this_.PER_D_BIRTH_DATE='2010-04-10' and this_.PER_T_FIRST_NAME='Johnny' and this_.PER_T_LAST_NAME='Be Good')

当然,配置可以更进一步。 例如,P6Spy知道如何将日志重定向到文件或Log4J(当前缺少SLF4J适配器,但是任何人都可以轻松编写一个代码)。

如果需要在应用程序服务器中使用P6Spy,则应在数据源级别在应用程序服务器本身上进行配置。 在这种情况下,将跟踪该数据源的每一次使用,无论是从Hibernate,TopLink,iBatis还是普通的JDBC。

例如,在Tomcat中,将spy.properties放在common / classes中,并更新数据源配置以使用P6Spy驱动程序。

可以在这里找到本文的源代码。

翻译自: https://blog.frankel.ch/debugging-hibernate-generated-sql/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值