Jakarta ee JavaEE:为什么直接使用JTA?

Jakarta ee JavaEE:为什么直接使用JTA?,jakarta-ee,jta,Jakarta Ee,Jta,我试图理解JTA,并使用Bitronix作为事务管理器(只是为了学习和理解)。我看着Bitronix中的代码,心里想:如果我使用的是JDBC,它本身就是事务性的(Connection可以提交/回滚),我为什么要编写这样的代码 现在,也许这段代码的要点是简单地演示如何在现有事务数据存储上使用Bitronix/JTA,但我仍然不知道它提供了什么固有的好处 然后,这个代码片段让我思考:“如果您使用的仅有两个主要数据源是数据库和消息代理,并且您分别使用JDBC/JMS与它们通信,而这两个标准(JDBC/

我试图理解JTA,并使用Bitronix作为事务管理器(只是为了学习和理解)。我看着Bitronix中的代码,心里想:如果我使用的是JDBC,它本身就是事务性的(
Connection
可以提交/回滚),我为什么要编写这样的代码

现在,也许这段代码的要点是简单地演示如何在现有事务数据存储上使用Bitronix/JTA,但我仍然不知道它提供了什么固有的好处

然后,这个代码片段让我思考:“如果您使用的仅有两个主要数据源是数据库和消息代理,并且您分别使用JDBC/JMS与它们通信,而这两个标准(JDBC/JMS)已经是事务性的,那么您为什么还需要使用JTA?!”

JTA是JDBC、JPA、JMS等都使用的某种“内部”javaeeapi;只有那些想用它做些疯狂的事的1%的人才会被公开曝光?还是我完全忽略了JTA的概念/适用性

我想我可以设想两个非JDBC和非JMS的用例来直接命中JTA,但由于我一开始对JTA非常模糊,我不知道这些用例是否偏离了轨道:

  • 也许你的应用程序中有一个复杂的I/O系统,并且有多个线程在磁盘上读写同一个文件。也许您会让每个线程使用一个事务来写入此文件。(是?!不是?!?)
  • 也许您有一个表示系统状态的状态机POJO,多个线程可以修改该机器。也许您会让每个线程使用一个事务来改变机器的状态。(是?!不是?!?)
我想我的问题的根源是:

  • 如果我的JPA(Hibernate)和/或JDBC调用已经是事务性的,为什么我要将它们包装在JTA begin->commit/rollback块中?JMS和消息传递系统也是如此
  • 在JPA/JDBC/JMS之外,使用JTA处理一系列操作有哪些用例
提前谢谢

您可以有一个同时覆盖数据库和消息服务的事务。我不知道没有JTA有什么办法可以做到

简单的概念示例。准确的代码并不重要:

开始JTA事务

将数据库中帐户345的AccountBalance设置为低100美元

将JMS消息“将100美元转账到其他银行账户#987”添加到队列

提交JTA事务

OtherBank是一个独立的银行,我们假设您通过JMS与它通信

开始事务和提交由JTA处理。如果将其添加到队列失败,撤回也会自动回滚

现实生活并不是那么简单,但这应该给你一个想法

编辑:

JTA可以在系统的任何部分能够正确实现的任何时候使用。通过实现这一点,资源可以参与分布式事务。乍一看,您提出的两个示例都可能实现
XAResource

“你的应用程序中有一个复杂的I/O系统,有多个线程从磁盘上的同一个文件读写。”-如果你仔细想想,这听起来像是一个数据库

“也许您有一个表示系统状态的状态机POJO,并且多个线程可以修改该机器。”-如果可以充分隔离更改,这肯定是一个候选


我认为准则的第一部分基本上是资源在逻辑上可以是
XAResource
s。换句话说,酸的概念是有意义的。第二,实现该接口是可能的,也是值得的(在尚未实现的地方)。

它不仅仅是回滚打开的事务,JTA提供了一个提供程序可以实现的接口,您的JDBC驱动程序和JMS提供程序已经做到了这一点,您可以实现自己的接口。这是基于开放标准的,可能值得一读

现在我们为什么想要这个

以马修斯的灾难为例:

Begin DB Transaction

Set AccountBalance $100 lower for Account #345 in database

Add JMS Message "Transfer $100 to OtherBank Account #987" to queue

*** DB power is unplugged while committing DB Transaction ***
不幸的是,JMS消息已经传到了另一家银行,这对于分布式事务来说是一个非常现实的问题

对于XA,这就是场景的结果:

DB Transation starts XA Transaction

Set AccountBalance $100 lower for Account #345 in database

JMS Connection joins XA Transaction 

Add JMS Message "Transfer $100 to OtherBank Account #987" to queue

Everything went okay and JTA context is ready to commit.

DB and JMS both agree that they are capable of commiting.

JTA instructs DB and JMS to commit.

All members of the transaction commit.
现在,您可能会问,如果在DB的最终提交过程中拔出电源插头,会发生什么情况。JMS队列已经提交,但是XA事务将保持打开状态,直到DB再次可用,此时它将再次指示DB提交(DB向我们承诺它可以提交,这是XA兼容的一部分)

JTA真正伟大之处在于,您可以轻松实现自己的定制XAResource,并与这个伟大的框架相结合

更新

因此,要回答您关于何时实施自定义事务的问题,您可以问自己以下问题:

  • 您的自定义状态或文件是否不能成为事务作用域中的最终代码块
  • 当外部系统(如DB或JMS)出现故障时,是否需要恢复自定义状态/文件
  • 对于外部系统,简单的getRollbackOnly()和setRollbackOnly()以及针对自定义代码的补偿处理(即显式还原自定义状态/文件)是否不足
  • 如果1、2和3的答案都是肯定的,那么您可能需要一个定制的XAResource,否则我认为这可能是过分的


    但是,如果您的代码是一个框架或库,它将由JavaEE空间中的业务逻辑登记,那么您可能需要为它实现一个XAResource

    我认为,首先要考虑的是解除TX管理器和TX系统的控制

    当我设计我的应用程序时,Transactional这个词表示我想做一些事情。我想把这个意图放在我的业务代码中,因为这应该是由业务需求驱动的

    我想