事务类型="RESOURCE_LOCAL 与 JTA-数据源



我遇到了一个使用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数据源";?有趣的是,尽管如此,应用程序似乎运行良好。有什么想法为什么它能正常工作吗?

<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数据源。

最新更新