嵌套事务和EJBContext的setRollbackOnly()(Nested Transaction and EJBContext's setRollbackOnly())

编程入门 行业动态 更新时间:2024-10-14 06:17:02
嵌套事务和EJBContext的setRollbackOnly()(Nested Transaction and EJBContext's setRollbackOnly())

我正在阅读Java EE 7的事务管理,我对嵌套事务的概念和EJBContext#setRollbackOnly()的功能感到困惑。

假设我有两个会话Bean, Bean1Impl和Bean2Impl ,它们的签名是:

@Stateless @TransactionManagement(TransactionManagementType.CONTAINER) public class Bean1Impl implements Bean1 { @Resource private EJBContext context; @TransactionAttribute(REQUIRED) public void method1() { try { //some operations such as persist(), merge() or remove(). }catch(Throwable th){ context.setRollbackOnly(); } } } @Stateless @TransactionManagement(TransactionManagementType.CONTAINER) public class Bean2Impl implements Bean2 { @Resource private EJBContext context; @TransactionAttribute(REQUIRED) public void method2() { try { //some operations such as persist(), merge() or remove(). //an exception has been thrown }catch(Throwable th){ context.setRollbackOnly(); } } }

如Java EE 7教程中所述 :

51.3.1.1必需属性

如果客户端在事务中运行并调用企业bean的方法,则该方法在客户端的事务中执行。 如果客户端未与事务关联,则容器在运行该方法之前启动新事务。

Required属性是使用容器管理的事务划分运行的所有企业bean方法的隐式事务属性。 除非需要覆盖其他事务属性,否则通常不会设置Required属性。 由于事务属性是声明性的,因此您可以在以后轻松更改它们。

在这种情况下,我不需要在方法Bean1Impl#method1()和Bean2Impl#method2()指定@TransactionAttribute(REQUIRED)注释声明。 我对吗?

因此在上面的代码中, Bean2Impl#method2()的事务将在Bean1Impl#method1()的事务中运行。

我可以将其视为嵌套交易吗?

如果在方法Bean2Impl#method2()抛出异常,最终会导致从catch块调用方法EJBContext.setRollbackOnly() ,并且正如预期的那样,它应该回滚在try块中执行的操作这种方法。 在这种情况下,事务会发生什么,以及Bean1Impl#method1() 。 它会被回滚吗? 我的意思是:

如果从Bean2Impl#method2()调用EJBContext.setRollbackOnly()会发生什么,

Bean2Impl#method2()在任何数据库操作(如persist,merge或remove Bean1Impl#method1()之前从方法Bean1Impl#method1()调用。 Bean2Impl#method2()在任何数据库操作(如persist,merge或remove Bean1Impl#method1()之后从方法Bean1Impl#method1()调用。

最后,如果方法Bean2Impl#method2()成功执行但在成功返回Bean2Impl#method2()后从Bean1Impl#method1()调用EJBContext.setRollbackOnly()会发生什么?

I am reading the Transaction Management of Java EE 7 and I get confused by the concept of nested transaction and the functionality of EJBContext#setRollbackOnly().

Say I have two Session Beans, Bean1Impl and Bean2Impl and their signatures are:

@Stateless @TransactionManagement(TransactionManagementType.CONTAINER) public class Bean1Impl implements Bean1 { @Resource private EJBContext context; @TransactionAttribute(REQUIRED) public void method1() { try { //some operations such as persist(), merge() or remove(). }catch(Throwable th){ context.setRollbackOnly(); } } } @Stateless @TransactionManagement(TransactionManagementType.CONTAINER) public class Bean2Impl implements Bean2 { @Resource private EJBContext context; @TransactionAttribute(REQUIRED) public void method2() { try { //some operations such as persist(), merge() or remove(). //an exception has been thrown }catch(Throwable th){ context.setRollbackOnly(); } } }

As stated in Java EE 7 Tutorial:

51.3.1.1 Required Attribute

If the client is running within a transaction and invokes the enterprise bean's method, the method executes within the client's transaction. If the client is not associated with a transaction, the container starts a new transaction before running the method.

The Required attribute is the implicit transaction attribute for all enterprise bean methods running with container-managed transaction demarcation. You typically do not set the Required attribute unless you need to override another transaction attribute. Because transaction attributes are declarative, you can easily change them later.

In this case I don't need to specify @TransactionAttribute(REQUIRED) annotation declaration in the methods Bean1Impl#method1() and Bean2Impl#method2(). Am I right?

So in the above code the transaction of Bean2Impl#method2() would be running within the transaction of Bean1Impl#method1().

Can I consider it as a Nested Transaction?

If there is an Exception has been thrown inside the method Bean2Impl#method2() which eventually would lead to a call to the method EJBContext.setRollbackOnly() from the catch block and as expected it should roll back the operations performed within the try block of this method. In this case what would happen to the transaction and as well as the Bean1Impl#method1(). Would it be rolled back as well? What I mean is:

What would happen if there is a call of EJBContext.setRollbackOnly() from Bean2Impl#method2() and

Bean2Impl#method2() is called from the method Bean1Impl#method1() before any database operation like persist, merge or remove. Bean2Impl#method2() is called from the method Bean1Impl#method1() after any database operation like persist, merge or remove.

And lastly what would happen if the method Bean2Impl#method2() get executed successfully but EJBContext.setRollbackOnly() is called from Bean1Impl#method1() after successful return of Bean2Impl#method2()?

最满意答案

要添加到@Philippe Marshall的正确答案和您的评论 - REQUIRES_NEW将创建一个独立于第一个的新事务。 它们不是嵌套的。 第一个事务暂停,而第二个事务处于活动状态。 一旦第二个事务提交,第一个事务就会恢复。

您不必手动设置setRollbackOnly() 。 如果需要,大多数PersistenceException都会这样做。 通过回滚您不需要的交易,您将无法获得任何收益。 例如,在查询数据时,您可能会收到NoResultException或NonUniqueResultException 。 它们不会导致事务回滚,因为持久性上下文和数据库之间不存在不一致的风险。

您既不需要指定@TransactionAttribute(REQUIRED)也不需要指定@TransactionManagement(TransactionManagementType.CONTAINER) - 两者都是默认设置。

编辑:回答你的进一步问题:

我假设在method2上有@TransactionAttribute(REQUIRES_NEW) ,因此有两个独立的事务。

如果存在导致在方法2中回滚事务的异常,则如果捕获到异常,则不会回滚method1的事务。 如果未捕获Exception ,则将回滚两个事务。

在事务上设置回滚标志时,无论是在DB操作之前还是之后都发生这种情况,因为整个事务都会回滚。

一旦method2返回,它的事务就会被提交。 之后从方法1回滚或提交事务对第一个事务的结果没有影响。

一般建议 - 不要抓住Throwable - 它太宽泛了,你可能会吞下你宁愿传播到表面的异常。

To add to @Philippe Marshall's correct answer and your comment - REQUIRES_NEW will create a new transaction, independent from the first one. They are not nested. The first transaction is suspended while the second is active. Once the second transaction commits, the first one is resumed.

You do not have to setRollbackOnly() manually. Most PersistenceExceptions will do that if needed. You will gain nothing by rolling back transactions that you don't have to. For example, when querying data, you may get a NoResultException or a NonUniqueResultException. They do not cause a transaction to be rolled back as there is no risk of inconsistencies between the persistence context and the DB.

You do not need to specify neither @TransactionAttribute(REQUIRED) nor @TransactionManagement(TransactionManagementType.CONTAINER)- both are the default settings.

EDIT: to answer your further questions:

I am assuming @TransactionAttribute(REQUIRES_NEW) on method2 and therefore two separate transactions.

If there is an Exception that leads to the rollback of the transaction in method2, the transaction from method1 will not be rolled back if the Exception is caught. If the Exception is not caught, both transactions will be rolled back.

When setting the rollback flag on a transaction, it does not matter whether it happens before or after DB operations, since the entire transaction is rolled back.

Once method2 returns, it's transaction is committed. Rolling back or committing the transaction from method1 afterwards has no influence on the results of the first transaction.

A general advice - do not catch Throwable - it is much too broad and you might swallow exceptions which you would rather let propagate to the surface.

更多推荐

本文发布于:2023-08-02 23:06:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1381917.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:嵌套   事务   EJBContext   Transaction   Nested

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!