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
根类别设为 DEBUG
或 TRACE
:
<logger name="org.hibernate" level="DEBUG" />
⚠️ 踩坑提醒:
- 日志量爆炸式增长,可能瞬间打满磁盘
- 大量内部实现细节,信息噪音极高
- 仅建议在本地调试或短时间生产抓包时使用
效果如下图所示:
简单粗暴,但代价高昂 ❌
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