Spring 事务 - 防止在未经检查的异常(RuntimeException)后回滚
Spring Transactions - Prevent rollback after unchecked exceptions (RuntimeException)
我无法阻止事务在 RuntimeException
之后回滚。
我的环境是 Spring 4.1 + Hibernate 3.6 + JTA (WebSphereUowTransactionManager) 运行 在 Websphere 8.0 上。
“doStuff”案例:有效
首先,一个按预期运行的简单案例。由于我 捕获了 RuntimeException,事务提交并成功创建了新资源。
@Service("fooService")
public class FooServiceImpl implements IFooService {
@Transactional
@Override
public void doStuff(Resource res){
authService.createResource(res, "ADMIN");
try {
throw new RuntimeException("SOMETHING");
} catch (RuntimeException e) {
e.printStackTrace();
}
}
“doStuff2”案例:有效
下一个也可以。我声明 noRollbackFor 并让事务提交:
@Transactional(noRollbackFor=RuntimeException.class)
@Override
public void doStuff2(Resource res){
authService.createResource(res, "ADMIN");
throw new RuntimeException("SOMETHING");
}
“doStuff12”案例:不起作用
最后是有问题的。不同之处在于,在这种情况下,第二次调用 authService.createResource
会引发异常。仅供参考,authService.createResource
仅标记为 @Transactional
,因此应用默认传播配置,它应该加入调用服务的事务。
@Transactional(noRollbackFor=RuntimeException.class)
@Override
public void doStuff12(Resource res){
authService.createResource(res, "ADMIN");
try{
res.setName("EXISTING-RESOURCE");
authService.createResource(res, "ADMIN");
}catch(RuntimeException e){
e.printStackTrace();
}
}
尽管 捕获 RuntimeException 并声明 noRollbackFor 属性,事务总是回滚。有什么解释吗??
记录跟踪信息:
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - Creating new transaction with name [null]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; '',+com.myorg.webapps.exception.ElementoYaExistente
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - Invoking WebSphere UOW action: type=1, join=false
org.springframework.transaction.support.TransactionSynchronizationManager TRACE - Initializing transaction synchronization
org.springframework.transaction.interceptor.TransactionInterceptor TRACE - Getting transaction for [com.myorg.test.service.impl.FooServiceImpl.doStuff12]
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - Creating new transaction with name [null]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - Invoking WebSphere UOW action: type=1, join=true
org.springframework.transaction.interceptor.TransactionInterceptor TRACE - Getting transaction for [com.myorg.authmgr.service.impl.AuthorizationServiceImpl.createResource]
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - Returned from WebSphere UOW action: type=1, join=true
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - Creating new transaction with name [null]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - Invoking WebSphere UOW action: type=1, join=true
org.springframework.transaction.interceptor.TransactionInterceptor TRACE - Getting transaction for [com.myorg.authmgr.service.impl.AuthorizationServiceImpl.createResource]
org.springframework.transaction.interceptor.RuleBasedTransactionAttribute TRACE - Applying rules to determine whether transaction should rollback on java.lang.Runtime: Couldn't create the resource, it already exists: EXISTING-RESOURCE
org.springframework.transaction.interceptor.RuleBasedTransactionAttribute TRACE - Winning rollback rule is: null
org.springframework.transaction.interceptor.RuleBasedTransactionAttribute TRACE - No relevant rollback rule found: applying default rules
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - Returned from WebSphere UOW action: type=1, join=true
org.springframework.transaction.jta.WebSphereUowTransactionManager TRACE - Triggering beforeCommit synchronization
org.springframework.transaction.jta.WebSphereUowTransactionManager TRACE - Triggering beforeCompletion synchronization
org.springframework.transaction.support.TransactionSynchronizationManager TRACE - Clearing transaction synchronization
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - Returned from WebSphere UOW action: type=1, join=false
据我所知,一旦事务方法抛出运行时异常并被事务拦截器拦截,事务就会被标记为仅回滚。即使从另一个事务方法调用此事务方法。
这对我来说很有意义:如果内部方法不能从异常中恢复,它就不能恢复,而外部方法不应该像什么都没发生一样。
如果您希望事务不回滚,您可以
- 使内部方法成为非事务性的
- 配置内部方法不回滚此异常
- 有两个内部方法:
- 一个是事务性的,旨在在还没有事务时调用,它只是委托给第二个
- 一个非事务性的,旨在作为已经存在的事务的一部分被调用
我无法阻止事务在 RuntimeException
之后回滚。
我的环境是 Spring 4.1 + Hibernate 3.6 + JTA (WebSphereUowTransactionManager) 运行 在 Websphere 8.0 上。
“doStuff”案例:有效
首先,一个按预期运行的简单案例。由于我 捕获了 RuntimeException,事务提交并成功创建了新资源。
@Service("fooService")
public class FooServiceImpl implements IFooService {
@Transactional
@Override
public void doStuff(Resource res){
authService.createResource(res, "ADMIN");
try {
throw new RuntimeException("SOMETHING");
} catch (RuntimeException e) {
e.printStackTrace();
}
}
“doStuff2”案例:有效
下一个也可以。我声明 noRollbackFor 并让事务提交:
@Transactional(noRollbackFor=RuntimeException.class)
@Override
public void doStuff2(Resource res){
authService.createResource(res, "ADMIN");
throw new RuntimeException("SOMETHING");
}
“doStuff12”案例:不起作用
最后是有问题的。不同之处在于,在这种情况下,第二次调用 authService.createResource
会引发异常。仅供参考,authService.createResource
仅标记为 @Transactional
,因此应用默认传播配置,它应该加入调用服务的事务。
@Transactional(noRollbackFor=RuntimeException.class)
@Override
public void doStuff12(Resource res){
authService.createResource(res, "ADMIN");
try{
res.setName("EXISTING-RESOURCE");
authService.createResource(res, "ADMIN");
}catch(RuntimeException e){
e.printStackTrace();
}
}
尽管 捕获 RuntimeException 并声明 noRollbackFor 属性,事务总是回滚。有什么解释吗??
记录跟踪信息:
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - Creating new transaction with name [null]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; '',+com.myorg.webapps.exception.ElementoYaExistente
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - Invoking WebSphere UOW action: type=1, join=false
org.springframework.transaction.support.TransactionSynchronizationManager TRACE - Initializing transaction synchronization
org.springframework.transaction.interceptor.TransactionInterceptor TRACE - Getting transaction for [com.myorg.test.service.impl.FooServiceImpl.doStuff12]
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - Creating new transaction with name [null]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - Invoking WebSphere UOW action: type=1, join=true
org.springframework.transaction.interceptor.TransactionInterceptor TRACE - Getting transaction for [com.myorg.authmgr.service.impl.AuthorizationServiceImpl.createResource]
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - Returned from WebSphere UOW action: type=1, join=true
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - Creating new transaction with name [null]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - Invoking WebSphere UOW action: type=1, join=true
org.springframework.transaction.interceptor.TransactionInterceptor TRACE - Getting transaction for [com.myorg.authmgr.service.impl.AuthorizationServiceImpl.createResource]
org.springframework.transaction.interceptor.RuleBasedTransactionAttribute TRACE - Applying rules to determine whether transaction should rollback on java.lang.Runtime: Couldn't create the resource, it already exists: EXISTING-RESOURCE
org.springframework.transaction.interceptor.RuleBasedTransactionAttribute TRACE - Winning rollback rule is: null
org.springframework.transaction.interceptor.RuleBasedTransactionAttribute TRACE - No relevant rollback rule found: applying default rules
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - Returned from WebSphere UOW action: type=1, join=true
org.springframework.transaction.jta.WebSphereUowTransactionManager TRACE - Triggering beforeCommit synchronization
org.springframework.transaction.jta.WebSphereUowTransactionManager TRACE - Triggering beforeCompletion synchronization
org.springframework.transaction.support.TransactionSynchronizationManager TRACE - Clearing transaction synchronization
org.springframework.transaction.jta.WebSphereUowTransactionManager DEBUG - Returned from WebSphere UOW action: type=1, join=false
据我所知,一旦事务方法抛出运行时异常并被事务拦截器拦截,事务就会被标记为仅回滚。即使从另一个事务方法调用此事务方法。
这对我来说很有意义:如果内部方法不能从异常中恢复,它就不能恢复,而外部方法不应该像什么都没发生一样。
如果您希望事务不回滚,您可以
- 使内部方法成为非事务性的
- 配置内部方法不回滚此异常
- 有两个内部方法:
- 一个是事务性的,旨在在还没有事务时调用,它只是委托给第二个
- 一个非事务性的,旨在作为已经存在的事务的一部分被调用