[SPRING] 왜 트랜잭션은 RuntimeException에서 롤백하지만 SQLException은 그렇지 않다.
SPRING왜 트랜잭션은 RuntimeException에서 롤백하지만 SQLException은 그렇지 않다.
Spring에서 관리하는 서비스 메소드를 사용하여 데이터베이스 삽입을 관리합니다. 여러 개의 insert 문이 있습니다.
@Transactional
public void insertObservation(ObservationWithData ob) throws SQLException
{
observationDao.insertObservation(ob.getObservation());
// aop pointcut inserted here in unit test
dataDao.insertData(ob.getData());
}
두 번째 삽입을 호출하기 전에 예외를 throw하는 두 개의 단위 테스트가 있습니다. 예외가 RuntimeException이면 트랜잭션이 롤백됩니다. 예외가 SQLException 인 경우 첫 번째 삽입이 지속됩니다.
나는 당황 스럽다. 누구나 트랜잭션이 SQLException에 롤백되지 않는 이유를 말해 줄 수 있습니까? 누구든지 이것을 관리하는 방법을 제안 할 수 있습니까? 나는 SQLException을 잡아서 RuntimeException을 던질 수 있지만, 그것은 이상하게 보입니다.
해결법
-
==============================
1.이것은 정의 된 동작입니다. 문서에서 :
이것은 정의 된 동작입니다. 문서에서 :
이는 모든 Spring 트랜잭션 API에서 공통된 동작이다. 기본적으로 트랜잭션 코드 내에서 RuntimeException이 throw되면 트랜잭션이 롤백됩니다. 체크 된 예외 (RuntimeException이 아닌)가 발생하면 트랜잭션은 롤백되지 않습니다.
이 배후의 이론적 근거는 RuntimeException 클래스는 일반적으로 복구 할 수없는 오류 조건을 나타 내기 위해 Spring에 의해 사용된다는 것입니다.
원하는 경우이 동작을 기본값에서 변경할 수 있습니다. 그러나이를 수행하는 방법은 Spring API 사용 방법과 트랜잭션 관리자 설정 방법에 따라 다릅니다.
-
==============================
2.Spring은 RuntimeExceptions (DataAccessExceptions를 사용하여 SQLExceptions 또는 ORM의 예외를 래핑하는 것을 포함)를 광범위하게 사용하여 예외로부터 복구가없는 경우를 대비합니다. 그것은 서비스 위의 레이어가 어떤 것을 알 필요가 있지만 트랜잭션이 방해 받기를 원하지 않는 경우에 체크 된 예외를 사용하기를 원한다고 가정합니다.
Spring은 RuntimeExceptions (DataAccessExceptions를 사용하여 SQLExceptions 또는 ORM의 예외를 래핑하는 것을 포함)를 광범위하게 사용하여 예외로부터 복구가없는 경우를 대비합니다. 그것은 서비스 위의 레이어가 어떤 것을 알 필요가 있지만 트랜잭션이 방해 받기를 원하지 않는 경우에 체크 된 예외를 사용하기를 원한다고 가정합니다.
Spring을 사용하고 있다면 jdbc-wrapping 라이브러리와 DataAccessException 번역 기능을 사용할 수도 있습니다. 유지 보수해야 할 코드의 양이 줄어들고보다 의미있는 예외를 제공합니다. 구현 특정 예외를 throw하는 서비스 계층을 갖는 것도 나쁜 냄새입니다. 사전 스프링 방식은 구현 특정 예외를 래핑하는 구현에 독립적 인 검사 예외를 작성하는 것이 었습니다. 이로 인해 많은 작업량과 비 대한 코드 기반이 발생했습니다. 봄의 길은 그러한 문제를 피한다.
이런 식으로 Spring을 선택하게 된 이유를 알고 싶다면 아마도 AOP를 사용하여 트랜잭션 처리를 추가하기 때문일 것입니다. 래핑하는 메소드의 서명을 변경할 수 없으므로 검사 된 예외는 옵션이 아닙니다.
-
==============================
3.@Transactional의 경우 기본적으로 롤백은 런타임에 대해 발생하며 체크되지 않은 예외 만 발생합니다. 따라서, 체크 된 예외 SQLException은 트랜잭션의 롤백을 트리거하지 않습니다. rollbackFor 및 noRollbackFor 주석 매개 변수를 사용하여 동작을 구성 할 수 있습니다.
@Transactional의 경우 기본적으로 롤백은 런타임에 대해 발생하며 체크되지 않은 예외 만 발생합니다. 따라서, 체크 된 예외 SQLException은 트랜잭션의 롤백을 트리거하지 않습니다. rollbackFor 및 noRollbackFor 주석 매개 변수를 사용하여 동작을 구성 할 수 있습니다.
@Transactional(rollbackFor = SQLException.class) public void insertObservation(ObservationWithData ob) throws SQLException { observationDao.insertObservation(ob.getObservation()); // aop pointcut inserted here in unit test dataDao.insertData(ob.getData()); }
from https://stackoverflow.com/questions/7125837/why-does-transaction-roll-back-on-runtimeexception-but-not-sqlexception by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] JdbcDaoSupport는 무엇을 위해 사용됩니까? (0) | 2019.01.11 |
---|---|
[SPRING] Weblogic에 스프링 부트 응용 프로그램 배포 (0) | 2019.01.11 |
[SPRING] 스프링 빈 정의의 우선 순위는 무엇입니까? (0) | 2019.01.11 |
[SPRING] "잠금을 얻으려고 할 때 교착 상태가 발견되었습니다. 트랜잭션을 다시 시작하십시오. " (0) | 2019.01.11 |
[SPRING] Spring MVC : 컨트롤러 메소드 매개 변수에 요청 속성을 바인드한다. (0) | 2019.01.11 |