How to prevent JPA from rolling back transaction?

前端 未结 2 1309
礼貌的吻别
礼貌的吻别 2020-12-16 20:31

Methods invoked:
1. Struts Action
2. Service class method (annotated by @Transactional)
3. Xfire webservice call

Everything including struts (Delegatin

相关标签:
2条回答
  • 2020-12-16 21:17

    Managed to create a test case for this problem:

    @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();
        }
    }
    

    FakeService:

    @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);
        }
    }
    

    WebService:

    @Transactional(readOnly = true)
    public class WebService {
        public void letsThrowAnException() {
            throw new XFireRuntimeException("test!");
        }
    }
    

    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:

    @Transactional(noRollbackFor={XFireRuntimeException.class})
        public void letsThrowAnException() {
    

    Now the transaction isn't being rolled back and I can commit the changes to Order.

    0 讨论(0)
  • 2020-12-16 21:20

    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 replace Exception.class with WebServiceOrderFailed.class.

    0 讨论(0)
提交回复
热议问题