调用的方法:
1. Struts Action
2.服务类方法(@Transactional注解)
3.Xfire web服务调用
包括 struts (DelegatingActionProxy) 和事务在内的一切都使用 Spring 配置。
持久化是通过 JPA/Hibernate 完成的。
有时网络服务会抛出未经检查的异常。我捕获了这个异常并抛出了一个已检查的异常。我不希望事务回滚,因为 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不回滚事务?
最佳答案
设法为此问题创建了一个测试用例:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"file:web/WEB-INF/spring/applicationContext.xml",
"file:web/WEB-INF/spring/services.xml"})
@Transactional
public class DoNotRollBackTest {
@Autowired FakeService fakeService;
@Test
@Rollback(false)
public void testRunXFireException() {
fakeService.doSomeTransactionalStuff();
}
}
伪造服务:
@Service
public class FakeService {
@Autowired private EcomService ecomService;
@Autowired private WebService webService;
@Transactional(noRollbackFor={XFireRuntimeException.class})
public void doSomeTransactionalStuff() {
Order order = ecomService.findOrderById(459);
try {
webService.letsThrowAnException();
} catch (XFireRuntimeException e) {
System.err.println("Caugh XFireRuntimeException:" + e.getMessage());
}
order.setBookingType(BookingType.CAR_BOOKING);
ecomService.persist(order);
}
}
网络服务:
@Transactional(readOnly = true)
public class WebService {
public void letsThrowAnException() {
throw new XFireRuntimeException("test!");
}
}
这将重新创建回滚异常。
然后我意识到该事务可能在 WebService.letsThrowAnException 中被标记为 rollbackOnly,因为 WebService 也是事务性的。我转到注释:
@Transactional(noRollbackFor={XFireRuntimeException.class})
public void letsThrowAnException() {
现在事务没有被回滚,我可以将更改提交到 Order。
关于java - 如何防止 JPA 回滚事务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1701750/