2

我正在开发一个遗留应用程序。我们正在将它从 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 事务管理器将在afterPropertiesSetUserTransaction、TransactionManager 和 TransactionSynchronizationRegistry 中设置为自己。

看来我实际上仍然在 CMT 中泄漏数据,但是由于事务通常提交,因此如果没有调试器或不自然地强制错误,很难感知/观察到这一点。

看来我的问题是我已经部分绕过了 JCA,以至于 JCA 使用了不同的 TransactionManager。

部分答案- 因为我已经在 CMT 和 BMT 的混合中正确地看到了这个事务,所以我知道可以让 BMT 事务以一种方法启动并以另一种方法提交。

问题仍然存在:如果 Spring 中的 CMT 管理的 servlet 生成一个新线程并使用计划 thread.start() 启动该线程,那么期望该新线程中的 BMT 能够按所述管理其事务是否合理?以上?

4

1 回答 1

2

从 JTA 1.1 规范(http://download.oracle.com/otn-pub/jcp/jta-1.1-spec-oth-JSpec/jta-1_1-spec.pdf)第 3.1 节,很明显,事务是绑定的到线程。这由 TransactionManager 管理。如果线程是创建事务的线程,则应该能够期望线程能够在事务上下文中执行操作。

请注意,嵌套事务的支持是可选的,正如在 JTA 规范的同一部分中引用的那样。

我遇到的实际问题是托管数据源使用的事务管理器实例与我们在应用程序中使用的 bean 不同。更改应用程序代码以执行容器提供的 TransactionManager 的 JNDI 查找允许托管数据源参与与应用程序相同的事务。

于 2013-11-19T20:59:51.910 回答