transaction-type="RESOURCE_LOCAL with jta-data-source

问题描述

我遇到了一个使用 OpenJPA 和 DB2 运行在 Websphere Liberty 18 上的旧项目。在 persistence.xml 文件中有一个具有以下声明的持久单元:

<persistence-unit name="my-pu" transaction-type="RESOURCE_LOCAL">       
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<jta-data-source>jdbc/my-data-source</jta-data-source>
</persistence-unit>

如果我们使用 RESOURCE_LOCAL 事务并且有代码来手动管理分散在整个应用程序中的事务,那么数据源不应该声明为“非 jta-data-来源”?有趣的是,尽管如此,该应用程序似乎运行良好。任何想法为什么它工作正常?

解决方法

<non-jta-data-source> 指定拒绝在 JTA 事务中登记的数据源。这意味着,如果您执行 userTransaction.begin(或利用容器为您启动事务的任何 API),并对数据源(在 Liberty 中标记为 transactional="false")执行一些操作,则操作将不是包含 JTA 事务的一部分,并且可以独立提交或回滚。这绝对是一种高级模式,如果您不知道自己在做什么,或者暂时忘记了数据源未登记,则最终可能会编写破坏数据的代码。此时,您可能想知道为什么 JPA 甚至有这样的选项。我希望它根本不适合最终用户使用 JPA 编程模型,而是真正用于 JPA 持久性提供程序(Hibernate/EclipseLink/OpenJPA)实现。例如,如果您考虑一个 JTA 事务在线程上处于活动状态的场景,并且您通过 JPA 执行操作,其中 JPA 持久性提供程序需要为您生成唯一密钥,并且持久性提供程序需要运行一些数据库命令来保留下一个唯一键块,JPA 持久性提供程序不能只在您的事务中执行此操作,因为您最终可能会回滚它,然后相同的唯一键块可能会被发出两次并且会发生错误。 JPA 持久性提供程序确实需要暂停您的事务,运行自己的事务,然后恢复您的事务。在我看来,暂停/恢复将是这里的自然解决方案,但 JTA 规范没有提供获取 TransactionManager 的标准方法,所以我的猜测是 JPA 规范为这种需要一个绕过事务登记的数据源作为替代。 JPA 提供程序可以在非 jta 数据源上运行自己的事务操作,而您的 JTA 事务继续不受其影响。您还会注意到我选择的示例,它不适用于通过 JPA 的许多路径。如果您的 JPA 实体配置为让数据库生成唯一键,那么持久性提供程序不需要在非 jta 数据源上执行自己的数据库操作。如果您不使用 JTA 事务,那么持久性提供程序不需要担心在您的事务中登记,因为它可以只使用不同的连接,因此它也不需要非 jta 数据源。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...