[SPRING] JPA가 트랜잭션을 롤백하는 것을 방지하는 방법은 무엇입니까?
SPRINGJPA가 트랜잭션을 롤백하는 것을 방지하는 방법은 무엇입니까?
호출 된 메소드 : 1. Struts 액션 2. 서비스 클래스 메소드 (@Transactional에 의해 주석 됨) 3. Xfire 웹 서비스 호출
Struts (DelegatingActionProxy) 및 트랜잭션을 포함한 모든 것이 Spring으로 구성됩니다.
영속성은 JPA / Hibernate로 수행됩니다.
때로는 webservice가 검사되지 않은 예외를 throw합니다. 이 예외를 catch하고 확인 된 예외를 throw합니다. 웹 서비스 예외가 현재 상태를 변경하기 때문에 트랜잭션이 롤백되는 것을 원하지 않습니다. 나는 다음과 같은 방법으로 주석을 달았다.
@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으로 이것을 재현하려 할 때, 트랜잭션은 롤백으로 표시되지 않고 트랜잭션을 커밋 할 수 있습니다.
스프링이 트랜잭션을 롤백하지 않게하려면 어떻게해야합니까?
해결법
-
==============================
1.이 문제에 대한 테스트 케이스를 작성하려면 다음과 같이 관리해야합니다.
이 문제에 대한 테스트 케이스를 작성하려면 다음과 같이 관리해야합니다.
@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); } }
웹 서비스:
@Transactional(readOnly = true) public class WebService { public void letsThrowAnException() { throw new XFireRuntimeException("test!"); } }
이렇게하면 롤백 예외가 다시 작성됩니다.
그런 다음 WebService가 트랜잭션이기 때문에 트랜잭션이 WebService.letsThrowAnException에서 rollbackOnly로 표시되고 있음을 알았습니다. 특수 효과로 옮겼습니다.
@Transactional(noRollbackFor={XFireRuntimeException.class}) public void letsThrowAnException() {
이제 트랜잭션이 롤백되지 않고 주문 변경 사항을 커밋 할 수 있습니다.
-
==============================
2.Spring이 볼 수있는 곳에 예외를 던져서는 안된다. 이 경우 WebServiceOrderFailed ()를 throw하면 안됩니다. 해결책은 코드를 두 가지 방법으로 분리하는 것입니다. 첫 번째 메서드는 오류 처리를 수행하고 예외를 반환하고 외부 메서드는 트랜잭션을 만듭니다.
Spring이 볼 수있는 곳에 예외를 던져서는 안된다. 이 경우 WebServiceOrderFailed ()를 throw하면 안됩니다. 해결책은 코드를 두 가지 방법으로 분리하는 것입니다. 첫 번째 메서드는 오류 처리를 수행하고 예외를 반환하고 외부 메서드는 트랜잭션을 만듭니다.
[편집] noRollbackFor에 관해서는 : Exception.class를 WebServiceOrderFailed.class로 대체하십시오.
from https://stackoverflow.com/questions/1701750/how-to-prevent-jpa-from-rolling-back-transaction by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] 스프링 보안 / j_spring_security_check을 찾을 수 없음 404 (0) | 2019.02.11 |
---|---|
[SPRING] 스프링 데이터 JPA : 모델을 우아하게 업데이트하는 방법은 무엇입니까? (0) | 2019.02.11 |
[SPRING] javacfig에서 'springSecurityFilterChain'이라는 Bean이 정의되지 않았습니다. (0) | 2019.02.11 |
[SPRING] MaxUploadSizeExceededException은 Spring에서 예외 처리 메소드를 호출하지 않습니다. (0) | 2019.02.10 |
[SPRING] Spring Controller에서 브라우저의 CSV 데이터를 반환하는 방법 (0) | 2019.02.10 |