1. 概述

Hibernate 作为 ORM 框架,帮我们屏蔽了大部分数据库交互的复杂性,开发效率大幅提升 ✅。但这也带来了一个副作用:一旦出现 SQL 相关的问题,排查起来非常困难,毕竟我们看不到底层到底执行了什么。

这时候,开启 Hibernate 的日志就显得尤为重要。通过日志,我们可以看到 Hibernate 生成的 SQL、绑定的参数、执行耗时等关键信息,快速定位问题。

本文将系统性地介绍 Hibernate 中几种关键的日志级别配置,帮助你在开发和调试中游刃有余


2. 日志 SQL 语句

最基础的需求是看到 Hibernate 生成的 SQL。这只需要开启 org.hibernate.SQL 这个日志类别,并将其级别设为 DEBUG 即可。

不同日志框架的配置方式如下:

Log4j

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

Log4j2

<Logger name="org.hibernate.SQL" level="debug"/>

Logback

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

配置后,日志中会出现类似以下内容:

2019-12-07 23:04:23 | DEBUG | [main] o.h.SQL:127 - insert into Employee 
(employeeNumber, name, title, id) values (?, ?, ?, ?)
2019-12-07 23:04:23 | DEBUG | [main] o.h.SQL:127 - select employee0_.id as id1_0_, 
employee0_.employeeNumber as employee2_0_, employee0_.name as name3_0_, 
employee0_.title as title4_0_ from Employee employee0_

⚠️ 注意:这里看到的 SQL 中参数仍为 ?,实际值并未打印。如果需要查看具体参数值,得进一步配置。


3. 日志参数值

光看 SQL 有时不够,比如你怀疑是某个参数传错了导致查询为空。这时就需要开启参数绑定日志。

Hibernate 使用 org.hibernate.type.descriptor.sql 类别,并在 TRACE 级别下输出参数绑定和结果提取信息。

Log4j

<logger name="org.hibernate.type.descriptor.sql"> 
    <level value="trace"/> 
</logger>

Log4j2

<Logger name="org.hibernate.type.descriptor.sql" level="trace"/>

Logback

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

开启后日志会变成这样:

2019-12-07 23:04:23 | DEBUG | [main] o.h.SQL:127 - insert into Employee (employeeNumber, name, title, id) 
values (?, ?, ?, ?)
2019-12-07 23:04:23 | TRACE | [main] o.h.t.d.s.BasicBinder:64 - binding parameter [1] 
as [VARCHAR] - [001]
2019-12-07 23:04:23 | TRACE | [main] o.h.t.d.s.BasicBinder:64 - binding parameter [2] 
as [VARCHAR] - [John Smith]
2019-12-07 23:04:23 | TRACE | [main] o.h.t.d.s.BasicBinder:52 - binding parameter [3] 
as [VARCHAR] - [null]
2019-12-07 23:04:23 | TRACE | [main] o.h.t.d.s.BasicBinder:64 - binding parameter [4] 
as [BIGINT] - [1]
2019-12-07 23:04:23 | DEBUG | [main] o.h.SQL:127 - select employee0_.id as id1_0_, 
employee0_.employeeNumber as employee2_0_, employee0_.name as name3_0_, 
employee0_.title as title4_0_ from Employee employee0_
2019-12-07 23:04:23 | TRACE | [main] o.h.t.d.s.BasicExtractor:60 - extracted value ([id1_0_] :
 [BIGINT]) - [1]
2019-12-07 23:04:23 | TRACE | [main] o.h.t.d.s.BasicExtractor:60 - extracted value ([employee2_0_] :
 [VARCHAR]) - [001]
2019-12-07 23:04:23 | TRACE | [main] o.h.t.d.s.BasicExtractor:60 - extracted value ([name3_0_] :
 [VARCHAR]) - [John Smith]
2019-12-07 23:04:23 | TRACE | [main] o.h.t.d.s.BasicExtractor:50 - extracted value ([title4_0_] :
 [VARCHAR]) - [null]

✅ 关键点:

  • binding parameter 表示参数绑定
  • extracted value 表示结果提取
  • 两个日志类别(SQL 和参数)可独立开关,但建议同时开启,否则你看到一堆参数却不知道对应哪条 SQL,踩坑警告 ⚠️

4. 启用 Hibernate 统计信息

除了 SQL 和参数,Hibernate 还能提供执行统计信息,比如查询耗时、JDBC 连接开销、缓存命中率等,对性能调优非常有帮助。

要启用统计,分两步走:

步骤 1:开启统计功能

在 Hibernate 配置中设置:

<property name="hibernate.generate_statistics">true</property>

步骤 2:开启日志输出

org.hibernate.stat 类别的日志级别设为 DEBUG

配置完成后,你会看到类似以下日志:

2019-12-07 23:25:18 | DEBUG | [main] o.h.s.i.StatisticsInitiator:101 - Statistics initialized 
[enabled=true]
2019-12-07 23:25:19 | DEBUG | [main] o.h.s.i.StatisticsImpl:729 - HHH000117: HQL: 
from com.baeldung.hibernate.logging.Employee, time: 22ms, rows: 1
2019-12-07 23:25:19 | INFO  | [main] o.h.e.i.StatisticalLoggingSessionEventListener:258 - 
Session Metrics {
    55600 nanoseconds spent acquiring 1 JDBC connections;
    178600 nanoseconds spent releasing 1 JDBC connections;
    2167200 nanoseconds spent preparing 2 JDBC statements;
    2426800 nanoseconds spent executing 2 JDBC statements;
    0 nanoseconds spent executing 0 JDBC batches;
    0 nanoseconds spent performing 0 L2C puts;
    0 nanoseconds spent performing 0 L2C hits;
    0 nanoseconds spent performing 0 L2C misses;
    47098900 nanoseconds spent executing 1 flushes (flushing a total of 1 entities 
    and 0 collections);
    0 nanoseconds spent executing 0 partial-flushes (flushing a total of 0 entities 
    and 0 collections)
}

✅ 实战价值:

  • time: 22ms 可用于快速识别慢查询
  • Session Metrics 提供了会话级资源消耗,适合分析连接泄漏、批量操作效率等问题
  • 注意:统计功能本身有性能开销,生产环境务必关闭

5. 全量日志(深度调试)

当你遇到极其诡异的问题,怀疑是 Hibernate 内部状态机或缓存机制出了问题时,可以考虑开启全量日志。

只需将 org.hibernate 根类别设为 DEBUGTRACE

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

⚠️ 踩坑提醒:

  • 日志量爆炸式增长,可能瞬间打满磁盘
  • 大量内部实现细节,信息噪音极高
  • 仅建议在本地调试短时间生产抓包时使用

效果如下图所示:

hibernate logs

简单粗暴,但代价高昂 ❌


6. 总结

日志类别 用途 建议级别 生产环境
org.hibernate.SQL 查看生成的 SQL DEBUG ❌ 关闭
org.hibernate.type.descriptor.sql 查看参数绑定 TRACE ❌ 关闭
org.hibernate.stat 性能统计 DEBUG/INFO ⚠️ 按需开启
org.hibernate 全量日志 DEBUG/TRACE ❌ 禁用

✅ 核心建议:

  • 开发阶段:建议开启 SQL + 参数日志,提升 debug 效率
  • 测试/压测:可临时开启统计信息,辅助性能分析
  • 生产环境:全部关闭,避免性能损耗和日志污染

示例代码已整理至 GitHub:https://github.com/yourname/tutorials/tree/master/persistence-modules/hibernate-enterprise


原始标题:Various Logging Levels in Hibernate