Java 嵌套事务和 EJBContext 的 setRollbackOnly()
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20823798/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Nested Transaction and EJBContext's setRollbackOnly()
提问by Tapas Bose
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()
.
我正在阅读 Java EE 7 的事务管理,但对嵌套事务的概念和EJBContext#setRollbackOnly()
.
Say I have two Session Beans, Bean1Impl
and Bean2Impl
and their signatures are:
说我有两个会话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();
}
}
}
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.
51.3.1.1 必需属性
如果客户端在事务中运行并调用企业 bean 的方法,则该方法在客户端的事务中执行。如果客户端未与事务关联,则容器在运行该方法之前启动一个新事务。
Required 属性是使用容器管理的事务划分运行的所有企业 bean 方法的隐式事务属性。除非您需要覆盖另一个事务属性,否则您通常不会设置 Required 属性。由于事务属性是声明性的,您可以在以后轻松更改它们。
In this case I don't need to specify @TransactionAttribute(REQUIRED)
annotation declaration in the methods Bean1Impl#method1()
and Bean2Impl#method2()
. Am I right?
在这种情况下,我不需要@TransactionAttribute(REQUIRED)
在方法Bean1Impl#method1()
和Bean2Impl#method2()
. 我对吗?
So in the above code the transaction of Bean2Impl#method2()
would be running within the transaction of Bean1Impl#method1()
.
所以在上面的代码中, 的事务Bean2Impl#method2()
将在 的事务中运行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:
如果Exception
在方法内部抛出了一个Bean2Impl#method2()
,最终会导致EJBContext.setRollbackOnly()
从catch
块中调用该方法,并且正如预期的那样,它应该回滚在try
该方法的块内执行的操作。在这种情况下,交易以及Bean1Impl#method1()
. 也会回滚吗?我的意思是:
What would happen if there is a call of EJBContext.setRollbackOnly()
from Bean2Impl#method2()
and
如果有EJBContext.setRollbackOnly()
来自Bean2Impl#method2()
和的调用会发生什么
Bean2Impl#method2()
is called from the methodBean1Impl#method1()
before any database operation like persist, merge or remove.Bean2Impl#method2()
is called from the methodBean1Impl#method1()
after any database operation like persist, merge or remove.
Bean2Impl#method2()
Bean1Impl#method1()
在任何数据库操作(如持久化、合并或删除)之前从方法中调用。Bean2Impl#method2()
Bean1Impl#method1()
在任何数据库操作(如持久化、合并或删除)之后从方法中调用。
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()
?
最后,如果该方法Bean2Impl#method2()
成功执行但在成功返回后被EJBContext.setRollbackOnly()
调用会发生什么?Bean1Impl#method1()
Bean2Impl#method2()
采纳答案by kostja
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.
添加到@Philippe Marshall 的正确答案和您的评论中 -REQUIRES_NEW
将创建一个新的交易,独立于第一个交易。它们不是嵌套的。第一个事务暂停,而第二个事务处于活动状态。一旦第二个事务提交,第一个事务就会恢复。
You do not have to setRollbackOnly()
manually. Most PersistenceException
s 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.
您不必setRollbackOnly()
手动。PersistenceException
如果需要,大多数人会这样做。通过回滚不需要的事务,您将一无所获。例如,在查询数据时,您可能会得到 aNoResultException
或 a NonUniqueResultException
。它们不会导致事务回滚,因为持久性上下文和数据库之间不存在不一致的风险。
You do not need to specify neither @TransactionAttribute(REQUIRED)
nor @TransactionManagement(TransactionManagementType.CONTAINER)
- both are the default settings.
您不需要指定两者都不@TransactionAttribute(REQUIRED)
是@TransactionManagement(TransactionManagementType.CONTAINER)
- 两者都是默认设置。
EDIT: to answer your further questions:
编辑:回答您的进一步问题:
I am assuming @TransactionAttribute(REQUIRES_NEW)
on method2
and therefore two separate transactions.
我假设@TransactionAttribute(REQUIRES_NEW)
的method2
,因此两个独立的交易。
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.
如果在 中存在Exception
导致事务回滚的method2
,则method1
如果捕获到异常,则不会回滚来自事务的事务。如果Exception
没有被捕获,两个事务都将被回滚。
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.
一旦method2
返回,它的事务就被提交。从method1
之后回滚或提交事务对第一个事务的结果没有影响。
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.
一般建议 - 不要捕获Throwable
- 它太宽泛了,您可能会吞下您宁愿让其传播到表面的异常。
回答by Philippe Marschall
This is not nested transactions, JavaEE / JTA does not support nested transaction. If #method2()
is called from #method1()
it runs in the same transaction. If you want to have a different transaction you need #REQUIRES_NEW
. EJBContext.setRollbackOnly()
only works on the current transaction. Note there is a chance that after calling EJBContext.setRollbackOnly()
all operations on the transactional resource including reads will throw an exception (JBoss AS 5.1 did this, don't know the current behaviour).
这不是嵌套事务,JavaEE/JTA 不支持嵌套事务。如果#method2()
从#method1()
它调用它在同一个事务中运行。如果您想进行不同的交易,则需要#REQUIRES_NEW
. EJBContext.setRollbackOnly()
仅适用于当前事务。请注意,在调用EJBContext.setRollbackOnly()
包括读取在内的事务资源上的所有操作后,有可能会抛出异常(JBoss AS 5.1 这样做了,不知道当前的行为)。
Update:
更新:
}catch(Throwable th){
context.setRollbackOnly();
}
You don't need this for runtime exceptions, this is the default behaviour of EJBs.
对于运行时异常,您不需要这个,这是 EJB 的默认行为。