仅当子方法发生异常时事务不回滚
我使用 Hibernate + spring + @Transactional
注释来处理应用程序中的事务。
事务管理器声明如下:
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
这在大多数情况下工作得很好,但我发现一个问题,我有 2 个方法,都注释为 @Transactional:
package temp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
public class OuterTestService {
@Autowired
private InnerTestService innerTestService;
@Transactional
public void outerMethod() {
try {
innerTestService.innerTestMethod();
} catch (RuntimeException e) {
// some code here
}
}
}
并且
package temp;
import org.springframework.transaction.annotation.Transactional;
public class InnerTestService {
@Transactional
public void innerTestMethod() throws RuntimeException {
throw new RuntimeException();
}
}
当我调用 OuterTestService#outerMethod() 时,我得到一个异常,
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
因为只有一个事务(无嵌套事务),整个 outerTestMethod()
的事务被标记为仅回滚。
我发现我可以使用 noRollbackFor: 轻松克服这个问题,
package cz.csas.pdb.be.service.tempdelete;
import org.springframework.transaction.annotation.Transactional;
public class InnerTestService {
@Transactional(noRollbackFor = RuntimeException.class)
public void innerTestMethod() throws RuntimeException {
throw new RuntimeException();
}
}
但这必须在每个方法上显式使用。由于在测试(回滚)期间不会引发此错误,因此这是不可接受的。
我的问题 - 有没有一种方法可以自动(例如,不是对每个方法都显式)设置仅当启动事务的方法引发异常时才回滚事务(在本例中为 outerTestMethod()< /代码>)?
I'm using Hibernate + spring + @Transactional
annotations to handle transactions in my application.
Transaction manager is declared as follows:
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
This works well in most cases, but I've found a problem where I have 2 methods, both annotated @Transactional:
package temp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
public class OuterTestService {
@Autowired
private InnerTestService innerTestService;
@Transactional
public void outerMethod() {
try {
innerTestService.innerTestMethod();
} catch (RuntimeException e) {
// some code here
}
}
}
and
package temp;
import org.springframework.transaction.annotation.Transactional;
public class InnerTestService {
@Transactional
public void innerTestMethod() throws RuntimeException {
throw new RuntimeException();
}
}
When I invoke OuterTestService#outerMethod(), I get an exception
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
As there is only one transaction (no nested transactions), the whole outerTestMethod()
's transaction is marked as rollback-only.
I've found that I can easily overcome this using noRollbackFor:
package cz.csas.pdb.be.service.tempdelete;
import org.springframework.transaction.annotation.Transactional;
public class InnerTestService {
@Transactional(noRollbackFor = RuntimeException.class)
public void innerTestMethod() throws RuntimeException {
throw new RuntimeException();
}
}
But this has to be explicitly used on every method. Because this error is not raised during tests (which are rollbacked), this is not acceptable.
My question -- is there a way to automatically (eg. not explicitly for every method) set that transactions are rolled back only when an exception is raised from method which started the transaction (in this case, the outerTestMethod()
)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
创建另一个注释,例如
@NoRollbackTransactional
,类似于:并在您的方法上使用它。另一方面,我同意 Donal 的评论,您应该修改您的事务范围,恕我直言,从另一个
@Transactional
调用@Transactional
通常不是一个好主意。Create another annotation, e.g.
@NoRollbackTransactional
, something like:And use this on your methods. On the other hand I agree with Donal's comment, you should revise your transaction scopes, imho it is generally not a good idea to call
@Transactional
from another@Transactional
.您可能还需要关闭globalRollbackOnParticipationFailure。
当我在周围事务中有一个独立事务时,我遇到了这个问题。当独立事务失败时,周围的事务也会失败。
关闭参与标志为我解决了这个问题:
You may also need to turn off globalRollbackOnParticipationFailure.
I had this problem when I had an independent transaction within a surrounding transaction. When the independent transaction failed, it also failed the surrounding transaction.
Turning off the participation flag solved this for me: