EJB 3 CMT如何在不回滚子事务的情况下回滚第一个事务?

3

我正在使用一个带有EJB和CMT事务的应用程序。我有一个EJB(我们称其为EJB1),通过注释定义了一个CMT,使用“requires_new”:

@TransactionAttribute(TransactionAttributeType.REQUIRED)

由于目前还没有任何交易,因此它会创建一个。现在,这个EJB1调用另一个EJB(EJB2)。我在研究中发现的唯一创建另一个事务的方法是使用“requires_new”,例如:

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)

它可以完美地工作,新的事务已经创建。问题在于回滚的情况:当EJB2失败时,只有它的事务被回滚,正如预期的那样。当EJB1失败时,所有的事务也将被回滚,这也是预期的,但不是我所需要的。。。
我需要的类似,只有这个区别:当EJB1失败时,它应该被回滚,但如果EJB2没有失败,我希望它仍然提交。
我让自己清晰吗?当其父级失败时,我不想要子事务被回滚。我想为每个从主EJB调用的EJB都有独立的事务(就像一个并行的事务)。

你能否在EJB1之上再创建一层?我建议你应该在顶层编排对EJB1和EJB2的调用,并将它们分别放在不同的事务中。 - Sandip Dhummad
@Sandip 谢谢你的回复。我明白你的想法,简单而且肯定能解决我的问题,我之前还没有考虑到这个... 这将对我现在的代码产生很大的影响。但我仍然好奇 CMT 是否有任何解决方案,哈哈... 再次感谢,我会在寻找其他想法的同时研究实施你的想法所带来的影响。 - Rodrigo Leitão
2个回答

2
你提到的事务属性在你的场景中应该按照你的期望工作;如果对EJB2的调用成功,它将自动提交,因为它是requires_new。但是,在这种情况下,如果在EJB2调用之前出现未处理的异常,它甚至可能不会被调用,从而给人留下一切都正在回滚的印象。
如果不是这种情况,你还可以通过注入EJBContext并调用context.setRollbackOnly()来控制EJB1中的事务。这将标记当前事务在完成时将被回滚,并且它将按照你的期望工作。

嗨,Fabio,谢谢您的回复。我认为您没有理解我的问题,或者我没有完全理解您所说的内容。我需要的是:调用EJB1,然后它使用REQUIRES_NEW事务调用EJB2。EJB2返回而没有任何异常,并且其事务“已准备好提交”,只等待EJB1提交。但是,如果EJB1失败并回滚,它也会回滚我的EJB2事务,而我不想要这样,我希望EJB2的事务仍然被提交。我知道我的英语很混乱,所以再次感谢您的努力。 - Rodrigo Leitão
我在搜索你说的内容,现在开始认为我的概念可能是错的。这是正确的吗?实际上,REQUIRES_NEW将创建一个完全独立的事务,并且如果"父级"事务回滚,它不会回滚。这是我的错误吗?我的概念?再次感谢... - Rodrigo Leitão
你是对的;当你使用“Requires new”创建一个事务时,它将在自己的事务上下文中运行,并且与调用它的人无关。所以在这种情况下,你的EJB1会打开一个新的事务,因为它是“Required”(加入现有事务或如果不存在则创建一个新事务)。当代码到达对EJB2的方法调用时,由于“Requires new”,该方法调用将在完全不同的事务中运行;这意味着如果EJB2回滚,它不会影响EJB1上的事务。 - Fabio Kenji
如果EJB2处于"Requires new"状态并且成功调用,它将提交;EJB1只有在没有异常的情况下完成才会提交其更改。EJB2中的“Requires New”将使其不依赖于EJB1的事务。我不确定是否应该在事务中查找保存点,也许只是创建正确的事务属性并分离您的方法调用的问题? - Fabio Kenji
我会考虑这个的... 你可能是对的,关于分离我的方法...希望你也是对的,关于事务哈哈... =D 真的非常感谢你的耐心和解释... Abraços - Rodrigo Leitão
显示剩余2条评论

1

我无法确认您的陈述:

它完美地工作,新事务已创建。问题在于回滚情况:当EJB2失败时,只有它的事务会被回滚,正如预期的那样。当EJB1失败时,所有事务都会被回滚,也如预期的那样,但这不是我需要的...

我没有在EJB1的方法中使用任何注释(应默认为REQUIRED,我想)。而在EJB2的方法中使用了@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)注释。

EJB1调用了EJB2。在EJB2中,我保存了一个实体并离开了该方法。回到EJB1,我通过抛出异常导致了回滚。最终,EJB2的更改已持久化,尽管EJB1的更改肯定已被回滚。

此外,在离开EJB2之后,您已经可以在数据库中看到提交的更改(使用断点暂停了EJB1的执行)。


谢谢您的回复,但那已经是一年前的事了,我不确定那个案例发生了什么,也不确定我的问题假设是否正确。也许我当时弄错了,真的记不清了...抱歉... - Rodrigo Leitão
不介意,我只是想澄清一下,以防其他人遇到同样的问题访问这个网站。事实上,这也是我来这里的原因 :-D - Peter Wippermann

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接