21

我正在尝试了解 JTA 并使用 Bitronix 作为首选的事务管理器(只是为了学习和理解)。我在这里查看 Bitronix参考指南中的代码,我想知道:如果我使用 JDBC,它本身是事务性的(Connection可以提交/回滚),我为什么要编写这样的代码? !?!

现在,该代码片段的目的可能是简单地演示如何在现有的事务数据存储上使用 Bitronix/JTA,但我仍然没有得到它提供的内在好处。

然后,这个代码片段让我想到:“如果您使用的唯一两个主要数据源是数据库和消息代理,并且您使用 JDBC/JMS 分别与它们进行通信,并且这两个标准(JDBC/JMS)已经是事务性的,那么为什么你根本需要使用 JTA?!?!

JTA 是 JDBC、JPA、JMS 等都使用的某种“内部”Java EE API;并且只为那些想要用它做一些疯狂的事情的 1% 人公开曝光?还是我完全错过了 JTA 的想法/适用性?

我想我可以设想两个非 JDBC 和非 JMS 用例直接命中 JTA,但由于我首先对 JTA 非常模糊,我不知道这些情况是否偏离轨道:

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

我想我的问题的根源是:

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

提前致谢!

4

3 回答 3

26

它不仅仅是回滚打开的事务,JTA 提供了提供者可以实现的XAResource接口,您的 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 并与这个伟大的框架联系起来!

更新

因此,要回答有关何时实施自定义交易的问题,您可以问自己以下问题:

  1. 您的自定义状态或文件是否无法成为事务范围内的最终代码块?
  2. 您是否需要在外部系统(即 DB 或 JMS)出现故障时恢复您的自定义状态/文件?
  3. 外部系统的简单 getRollbackOnly() 和 setRollbackOnly() 以及自定义代码的补偿处理(即显式恢复自定义状态/文件)是否不足?

如果 1、2 和 3 的答案都是“是”,那么您可能需要自定义 XAResource,否则我认为这可能是矫枉过正。

但是,如果您的代码是一个框架或库,它将被 Java EE 空间中的业务逻辑征用,您可能希望为它实现一个 XAResource!

于 2012-07-02T10:41:48.670 回答
3

您可以拥有一个同时涵盖数据库和消息服务的事务。如果没有 JTA,我不知道有什么方法可以做到这一点。

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

开始 JTA 事务

为数据库中的帐户 #345 设置 AccountBalance 100 美元以下

将 JMS 消息“Transfer $100 to OtherBank Account #987”添加到队列

提交 JTA 事务

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

Begin Transaction 和 Commit 由 JTA 处理。如果将其添加到队列中失败,则提款也会自动回滚。

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

编辑:

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

“你的应用程序中有一个复杂的 I/O 系统,并且有多个线程读取/写入磁盘上的同一个文件。” - 如果您考虑一下,这听起来可能是一个数据库。

“也许你有一个代表系统状态的状态机 POJO,多个线程可以修改机器。” - 如果可以充分隔离更改,这绝对是一个候选者。

我认为量规的第一部分基本上是资源在逻辑上可以XAResources。换句话说,ACID 的概念是有意义的。第二个是实现该接口是可能的并且值得付出努力(在尚未实现的地方)。

于 2012-06-29T17:26:26.993 回答
0

In my opinion, the first consideration is to decorolate the TX manager and the TX system.

When I design my application, the word Transactional mark my intent to do something ACID. I want to put this intent in my business code as this should be driven by a business need.

I expect something magic (my container in the real life) will weave my tx intents correctly, depending the underlying TX system (database, jms broker, etc.)

Moreover, JTA defines somes interfaces to allow integration between an existing JTA system and a (eventually new, eventually exotic) TX system. For example: GigaSpaces XAP is an in-memory datagrid. It is not JMS, not SQL, but it's easy to plumb it as it provides a JTA integration. We could quote many other products...

Obviously, the killer example is the support for XA transactions between different systems (I give a point to Justin). My point is to say JTA has value even if you don't use XA transaction.

于 2015-09-21T16:49:00.907 回答