2011-08-19 3 views
18

데이터베이스 관리를위한 스프링 관리 서비스 메소드가 있습니다. 여러 개의 insert 문이 있습니다.왜 트랜잭션은 RuntimeException에서 롤백하지만 SQLException은 롤백하지 않습니다.

두 번째 삽입을 호출하기 전에 예외를 throw하는 두 가지 단위 테스트가 있습니다. 예외가 RuntimeException이면 트랜잭션이 롤백됩니다. 예외가 SQLException 인 경우 첫 번째 삽입이 지속됩니다.

나는 당황하고 있습니다. 누구나 트랜잭션이 SQLException에 롤백되지 않는 이유를 말해 줄 수 있습니까? 누구든지 이것을 관리하는 방법을 제안 할 수 있습니까? 나는 SQLException을 잡아서 RuntimeException을 던질 수있다. 그러나 그것은 이상하게 보인다.

+2

스카프 만의 대답과 Nathan의 팁에 따르면 DAO 레이어에서 모든 SQLExceptions를 발견했으며이를 Spring의 SQLExceptionTranslator를 사용하여 체크되지 않은 DataAccessExceptions로 변환했습니다. 이 Spring 포럼 게시물, http://forum.springsource.org/showthread.php?63549- Conceptual-context-information 및 Robert Martin의 오류 처리 장 "Clean Code, 민첩한 소프트웨어 장인 정신 안내서"(Prentice Hall, 2008)) 또한 체크되지 않은 예외를 던지면 더 좋은 모듈성을 유지하는 이유를 명확히하는 데 도움이되었습니다. – climmunk

답변

35

이것은 정의 된 동작입니다. docs :

RuntimeException은 롤백을 트리거하며 확인 된 예외는 그렇지 않습니다.

이것은 모든 Spring 트랜잭션 API에서 공통된 동작입니다. 기본적으로 RuntimeException이 트랜잭션 코드 내에서 throw되면 트랜잭션이 롤백됩니다. 확인 된 예외 (예 : RuntimeException 아님)가 발생하면 트랜잭션은 롤백되지 않습니다.

그 이유는 RuntimeException은 일반적으로 스프링에 의해 취해서 복구 할 수없는 오류 조건을 나타 내기 때문입니다.

이 동작은 원하는 경우 기본값에서 변경할 수 있지만이를 수행하는 방법은 Spring API를 사용하는 방법과 트랜잭션 관리자를 설정하는 방법에 따라 다릅니다.

+0

그래,이 문제를 완전히 이해하지는 못했지만 맞습니다. 응용 프로그램 코드에서 처리 (로그, 이동, 실행 중지 등) 할 수 있도록 확인 된 SQLException을 던지고 싶습니다. 그러나 트랜잭션이 성공하기를 원하지 않습니다.예외에 대해 롤백 할 각 트랜잭션 주석을 설정할 수 있지만 응용 프로그램 전체에 트랜잭션 관리자를 설정하는 것이 좋습니다. 기본 DataSourceTransactionManager를 구성하도록 즉시 설정할 수는 없습니다. 당신이 이것에 대해 더 부유 한 토론을 제안한다면, 나는 그것을 감사 할 것입니다. 나는 지금 봄 포럼으로 뛰어 들고있다. 감사! – climmunk

2

스프링은 RuntimeExceptions (예외로부터 복구가없는 경우에 DataAccessExceptions를 사용하여 SQLExceptions 또는 ORM의 예외를 래핑하는 것을 포함)를 광범위하게 사용합니다. 그것은 서비스 위의 레이어가 어떤 것을 알 필요가 있지만 트랜잭션이 방해 받기를 원하지 않는 경우에 체크 된 예외를 사용하기를 원한다고 가정합니다.

스프링을 사용하는 경우 jdbc-wrapping 라이브러리와 DataAccessException 번역 기능을 사용하면 유지 관리해야 할 코드의 양이 줄어들고보다 의미있는 예외가 제공됩니다. 구현 특정 예외를 throw하는 서비스 계층을 갖는 것도 나쁜 냄새입니다. 사전 스프링 방식은 구현 특정 예외를 래핑하는 구현에 독립적 인 검사 예외를 작성하는 것이 었습니다. 이로 인해 많은 작업량과 비 대한 코드 기반이 발생했습니다. 봄의 길은 그러한 문제를 피한다.

Spring이 이러한 방식으로 작업하게하는 이유를 알고 싶다면 AOP를 사용하여 트랜잭션 처리를 추가했기 때문일 수 있습니다. 래핑하는 메소드의 서명을 변경할 수 없으므로 검사 된 예외는 옵션이 아닙니다.

관련 문제