Spurious Application Server Warnings with Hibernate

    在一些具有非常严格的 XADataSource 实现的 JTA 环境中(目前是一些 WebLogic Server 和 WebSphere 版本),当 Hibernate 被配置为不考虑该环境的 JTA 事务管理器时,应用服务器日志中会出现虚假的警告或异常。这些警告或异常表明被访问的连接不再有效或 JDBC 访问不再有效,可能是因为事务不再活动。作为一个例子,这里有一个来自 WebLogic 的实际异常。

    1. java.sql.SQLException: The transaction is no longer active - status: 'Committed'. No
    2. further JDBC access is allowed within this transaction.

    另一个常见的问题是 JTA 事务后的连接泄漏,Hibernate 会话(以及潜在的底层 JDBC 连接)没有被正确关闭。

    你可以通过让 Hibernate 意识到 JTA 事务管理器来解决这些问题,它与 JTA 事务管理器同步(和 Spring 一起)。你有两个选择来做到这一点:

    • 将你的 Spring JtaTransactionManager Bean 传递给你的 Hibernate 设置。最简单的方法是在 LocalSessionFactoryBean Bean 的 jtaTransactionManager 属性中引用一个 bean(见 Hibernate 事务设置)。然后 Spring 将相应的 JTA 策略提供给 Hibernate。

    • 你也可以显式地配置 Hibernate 的 JTA 相关属性,特别是 "hibernate.transaction.coordinator_class""hibernate.connection.handling_mode",还有可能是 LocalSessionFactoryBean 的 "hibernateProperties"中的 "hibernate.transaction.jta.platform"(关于这些属性的详细信息,请参阅 Hibernate 的手册)。

    本节的其余部分描述了在 Hibernate 知道和不知道 JTA PlatformTransactionManager 的情况下发生的事件顺序。

    当 Hibernate 在配置时没有意识到 JTA 事务管理器,当 JTA 事务提交时,会发生以下事件:

    • JTA 事务提交。
    • Spring 的 JtaTransactionManager 与 JTA 事务同步,因此它被 JTA 事务管理器通过 afterCompletion 回调调用。
    • 在其他活动中,这种同步可以触发 Spring 对 Hibernate 的回调,通过 Hibernate 的 afterTransactionCompletion 回调(用于清除 Hibernate 缓存),然后对 Hibernate 会话进行明确的 close()调用,这导致 Hibernate 试图关闭 JDBC 连接。
    • 在某些环境下,这个 Connection.close() 调用会触发警告或错误,因为应用服务器不再认为 Connection 是可用的,因为事务已经提交了。

    当 Hibernate 配置了对 JTA 事务管理器的认知,当 JTA 事务提交时,会发生以下事件:

    • JTA 事务已准备好提交。
    • Spring 的 JtaTransactionManager 与 JTA 事务同步,所以事务会通过 JTA 事务管理器的 beforeCompletion 回调被调用。
    • Spring 知道 Hibernate 本身是同步于 JTA 事务的,所以它的行为与之前的方案不同。特别是,它与 Hibernate 的事务性资源管理保持一致。
    • JTA 事务提交。
    • Hibernate 与 JTA 事务同步,因此事务通过 JTA 事务管理器的 afterCompletion 回调被调用,并能正确地清除其缓存。