我正在开发一个遗留应用程序。我们正在将它从 JDBC 转移到带有声明性事务的 Spring 3.2 + Hibernate 4.1.12 + JTA 2。我看到容器管理事务 (CMT) 正在按预期进行事务处理和回滚。我们使用 Infinispan 作为二级缓存 (2LC)。有一个皱纹...
有一部分代码具有不同的入口点,在不同的线程中运行并使用编程事务或 Bean-Managed Transactions (BMT)。在 BMT 路径中,我看到在使用 CMT 的底层服务层中,交易正在与 BMT 结合,正如人们所希望和期望的那样。
两个入口点的持久性单元、数据源等都是相同的。在这两种情况下,Hibernate 自动刷新代码都知道有一个事务并刷新到数据库驱动程序。在 CMT 入口点,数据库驱动程序保存数据,直到被告知提交或回滚。在 BMT 路径中,数据在刷新时被推送到数据库中——后来的提交或回滚没有任何影响或明显的意义。事务管理器是 JtaTransactionManager。JtaTransactionManager 定义在带有@EnableTransactionManagement 的@Configuration 类中,以启用CMT 而不是<tx:annotation-driven/>
元素。
单例 JtaTransactionManager bean 与 ajuna UserTransaction 和 TransactionManager 通过jtaPropertyManager.getJTAEnvironmentBean().getTransactionManager()
和jtaPropertyManager.getJTAEnvironmentBean().getUserTransaction()
。UserTransaction 和 TransactionManager 都是原型 @Bean 定义。
我可以通过来自另一个查询工具的查询来确认数据是否在数据库中,以验证调试时的行为。
当我进行单元测试时,BMT 和 CMT 入口点的数据都按预期提交和回滚。
BMT 由一个类管理,该类以不同的方法开始和结束事务。它还具有执行实际工作单元的方法。BMT 的事务由 PlatformTransactionManager 发起,而不是 TransactionTemplate。该类由另一个具有管理逻辑流的逻辑的类驱动。我知道交易按预期开始和结束。在阅读各种其他讨论时,似乎暗示事务控制应该在一个方法中。我同意这将是首选,但它是否必要?
如果 Spring 中的 CMT 管理的 servlet 生成一个新线程并使用计划 thread.start() 启动该线程,那么期望该新线程中的 BMT 能够如上所述管理其事务是否合理?
数据源由 JNDI 检索。使用 XA 或非 XA 不会影响结果。
我无法发布代码。
作为参考,这里是第 11 章中关于事务的 Spring 3.1 文档的链接。
添加于 2013年 10 月 4 日- 我看到 Spring 使用基于感知容器JtaTransactionManagerBeanDefinitionParser
构建期望的。JtaTransactionManager
使用此功能时,JTA 事务管理器将在afterPropertiesSet
UserTransaction、TransactionManager 和 TransactionSynchronizationRegistry 中设置为自己。
看来我实际上仍然在 CMT 中泄漏数据,但是由于事务通常提交,因此如果没有调试器或不自然地强制错误,很难感知/观察到这一点。
看来我的问题是我已经部分绕过了 JCA,以至于 JCA 使用了不同的 TransactionManager。
部分答案- 因为我已经在 CMT 和 BMT 的混合中正确地看到了这个事务,所以我知道可以让 BMT 事务以一种方法启动并以另一种方法提交。
问题仍然存在:如果 Spring 中的 CMT 管理的 servlet 生成一个新线程并使用计划 thread.start() 启动该线程,那么期望该新线程中的 BMT 能够按所述管理其事务是否合理?以上?