如何防止JPA事务回滚?
调用的方法:
1.Struts动作
2.Service类方法(@Transactional注解)
3. Xfire webservice调用
包括struts(DelegatingActionProxy)和事务在内的一切都是用Spring配置的。
持久性是通过 JPA/Hibernate 完成的。
有时 Web 服务会抛出未经检查的异常。我捕获这个异常并抛出一个已检查的异常。我不希望事务回滚,因为 Web 服务异常更改了当前状态。我已经注释了这样的方法:
@Transactional(noRollbackFor={XFireRuntimeException.class, Exception.class})
public ActionForward callWS(Order order, ....) throws Exception
(...)
OrderResult orderResult = null;
try {
orderResult = webService.order(product, user)
} catch (XFireRuntimeException xfireRuntimeException) {
order.setFailed(true);
throw new WebServiceOrderFailed(order);
} finally {
persist(order);
}
}
我仍然遇到此异常:
org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly
当我尝试使用 junit 重现此情况时,事务未标记为回滚,并且仍然可以提交事务。
如何让Spring不回滚事务?
Methods invoked:
1. Struts Action
2. Service class method (annotated by @Transactional)
3. Xfire webservice call
Everything including struts (DelegatingActionProxy) and transactions is configured with Spring.
Persistence is done with JPA/Hibernate.
Sometimes the webservice will throw an unchecked exception. I catch this exception and throw a checked exception. I don't want the transaction to roll back since the web service exception changes the current state. I have annotated the method like this:
@Transactional(noRollbackFor={XFireRuntimeException.class, Exception.class})
public ActionForward callWS(Order order, ....) throws Exception
(...)
OrderResult orderResult = null;
try {
orderResult = webService.order(product, user)
} catch (XFireRuntimeException xfireRuntimeException) {
order.setFailed(true);
throw new WebServiceOrderFailed(order);
} finally {
persist(order);
}
}
I still get this exception:
org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly
When I try to reproduce this with junit, the transaction isn't marked for roll back and it's still possible to commit the transaction.
How do I make Spring not to roll back the transaction?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
设法为此问题创建一个测试用例:
FakeService:
WebService:
这将重新创建回滚异常。
然后我意识到该事务可能在 WebService.letsThrowAnException 中被标记为 rollbackOnly,因为 WebService 也是事务性的。我转向注释:
现在事务不会回滚,我可以将更改提交到订单。
Managed to create a test case for this problem:
FakeService:
WebService:
This will recreate the rollback-exception.
Then I realized that the transaction is probably being marked as rollbackOnly in WebService.letsThrowAnException since WebService is also transactional. I moved to annotation:
Now the transaction isn't being rolled back and I can commit the changes to Order.
您不能在 Spring 可以看到的地方抛出异常。在这种情况下,您不得抛出
WebServiceOrderFailed()
。解决方案是将代码分成两个方法。第一个方法执行错误处理并返回异常,外部方法创建事务。[编辑] 至于
noRollbackFor
:尝试将Exception.class
替换为WebServiceOrderFailed.class
。You must not throw an exception where Spring can see it. In this case, you must not throw
WebServiceOrderFailed()
. The solution is to split the code into two methods. The first method does the error handling and returns the exception, the outer method creates the transaction.[EDIT] As for
noRollbackFor
: Try to replaceException.class
withWebServiceOrderFailed.class
.