在finally中关闭Hibernate Session需谨慎:仅限openSession()创建且未被Spring托管的Session,否则应交由Spring自动管理;推荐用try-with-resources(Hibernate 5.2+)或HibernateTemplate回调机制。

在finally中安全关闭Hibernate的Session,关键不是“关不关”,而是“能不能关、该不该关、怎么关才不破坏Spring管理机制”。直接调用s.close()看似合理,实际极易引发连接池耗尽、IllegalStateException: Pool not open等故障——尤其在Spring整合环境下。
先搞清Session和Spring的绑定关系
Spring默认将Session与当前请求线程(ThreadLocal)绑定,生命周期由事务管理器统一控制。你手动调用getSession()拿到的Session,可能属于已有事务,也可能是一个独立新开的Session。Spring只负责关闭它自己开启并托管的Session;你主动close()一个被Spring托管的Session,会提前释放连接,导致后续同一事务内其他操作失败;而关闭一个未被Spring托管的Session,又可能因连接未归还池而累积泄漏。
正确做法:优先交给Spring自动管理
避免手动干预Session生命周期。推荐以下方式:
- 使用
getHibernateTemplate().find()或getHibernateTemplate().execute()——这些方法内部已确保Session在方法结束时正确释放 - 若需原生Session操作,改用
getHibernateTemplate().execute(session -> { ... })回调形式,Spring会自动处理打开与关闭 - 确需手动获取Session时,设置
HibernateTemplate.setAllowCreate(true),并配合SessionFactory.getCurrentSession()(注意:此Session受当前事务上下文管理,禁止调用close(),应交由Spring在事务提交/回滚后自动清理)
如果真要写finally块(极少数场景)
仅适用于脱离Spring事务管理的纯Hibernate环境(如独立工具类、批处理脚本),且必须满足:
立即学习“Java免费学习笔记(深入)”;
- Session由
sessionFactory.openSession()显式创建(非getCurrentSession()) - 确认该Session未参与任何Spring事务
- 关闭前判空,并捕获可能的
HibernateException
示例:
Session session = null;
try {
session = sessionFactory.openSession();
return session.createQuery("from User").list();
} finally {
if (session != null && session.isOpen()) {
try { session.close(); } catch (HibernateException e) { /* 记日志,不抛出 */ }
}
}
比finally更可靠:用try-with-resources(Hibernate 5.2+)
新版Hibernate Session实现了AutoCloseable,可直接用于try-with-resources:
try (Session session = sessionFactory.openSession()) {
return session.createQuery("from User").list();
} // 自动调用close(),无需finally
注意:该方式仅适用于openSession()创建的Session,getCurrentSession()返回的Session不可用此方式,否则会干扰Spring事务。


















