【发布时间】:2018-07-18 07:17:47
【问题描述】:
我是 JTA 的新手,目前正在深入研究它的规范。我还创建了一些示例项目来更快地深入研究这个主题。我使用 IBM WebSphere 9 作为运行时。
我创建了一个由 EJB 和 MDB 组成的简单项目。这个想法是我将一些 JMS 发送到队列,然后 MDB 获取此消息,处理它并使用本地接口调用 EJB(MDB 和 EJB 都位于同一个 EAR 中)。 EJB 将处理传入的对象,并使用 JDBC 通过 XA 数据源将其写入 Oracle 数据库。
MDB onMessage() 方法定义了 TransactionAttributeType.NOT_SUPPORTED,正如 JTA 所说,它应该在事务上下文之外运行。
从 MDB 调用的 EJB 的 process() 方法没有定义任何 TransactionAttributes,因为它来自 JTA,所以它应该有一个默认值 TransactionAttributeType.REQUIRES_NEW。因此,如果我没记错的话,它会在被调用时启动一个新的全局 TX,还是我错了?
我还创建了一个简单的 DAO 类,它获取 JDBC 连接并运行语句来存储从 EJB 接收的数据。它位于 EJB 旁边的包中的普通 Java 类中。
当我尝试运行项目时会出现问题,更具体地说,当我尝试从数据源获取连接时会出现问题。由于我使用的是 XA 数据源,所以会出现 XAER_PROTO 异常:
[7/17/18 16:32:52:771 GMT+01:00] 000001b4 WSRdbXaResour E DSRA0304E: 发生 XAException。 XAException 的内容和细节是:
XA 错误是:-6 XA 错误消息是:在不正确的上下文中调用了例程。 Oracle > 错误代码是:24776 Oracle 错误消息是:内部 XA 错误
花了一些时间调查这个问题后,我发现这个问题可能与 JTA 规范中的以下语句有关:
3.4.7 本地和全局事务
...
当使用同一个连接来执行本地和全局 交易,以下规则适用:
• 本地事务必须在之前提交(或回滚) 在连接中启动一个全局事务。
• 全局事务必须与连接解除关联 在任何本地事务开始之前。
所以我的问题是:
是一个 EJB 方法,用
TransactionAttributeType.REQUIRES_NEW注释在 JTA 方面启动一个全局 TX?我的假设是否正确,即从数据源检索新的 JDBC 连接会根据 JTA 启动新的本地事务?
如果以上所有内容都正确,那么实际上是否可以在全局 TX 下的 EJB 中使用纯 JDBC?或者我应该只从非事务性 EJB 调用 JDBC 相关的方法?
我是否应该将上述方法视为错误的方法?
我应该使用更抽象的 JTA 接口来处理数据库,而不是使用“普通”的 JDBC 方法吗?如果是这样,那么哪种方式更可取?
【问题讨论】:
标签: java jdbc ejb websphere jta