1. Checked Exception일 경우
사실 이 항목에 대한 설명을 위해 어제 java의 error와 exception에 대해 포스팅을 했다.
Checked Exception이 뭔지 모른다면 먼저 아래 포스팅을 보고 오는 것을 추천!
[Java] Error, Checked Exception, Unchecked Exception 비교
자바에서는 예외를 크게 Error와 Exception으로 구분하고, Exception은 RuntimeException 상속 여부에 따라 Checked Exception, Unchecked Exception으로 구분된다. Error 시스템에 비정상적인 상황이 발생한 경..
ynzu-dev.tistory.com
Checked Exception는 예외상황 발생시 롤백처리를 하지 않는다.
Spring의 트랜젝션 처리를 하는 클래스를 살펴보면 completeTransactionAfterThrowing 라는 메소드가 있고, 이 메소드 안엔 롤백을 하기 전에 처리하는 부분이 있다.
if (txInfo.transactionAttribute.rollbackOn(ex)) {
try {
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
} catch( ) {
}
//생략
}
else {
try {
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
}catch( ) {
}
//생략
}
이를 추적해면 아래와 같은 소스를 발견할 수 있는데 RuntimeException이거나 Error인 경우만 롤백을 실행하는 것을 알 수 있다. 스프링프레임워크는 EJB의 관습을 따르기 때문이다.
@Override
public boolean rollbackOn(Throwable ex) {
return (ex instanceof RuntimeException || ex instanceof Error);
}
하지만 checked exception의 경우에도 롤백 시켜야될 상황이 있다면 어떻게 해야할까?
- 방법 1
@Transactional 속성을 보면 rollbackOn이 있다. 이 속성에 해당하는 exception을 추가해주면 된다. exception은 콤마(,)로 구분하여 여러개 추가할 수 있다. (rollbackFor인 경우도 있음.. 버전에 따라 다른듯?)
@Transactional(rollbackOn = {Exception.class})
- 방법 2
catch 부분에 RuntimeException을 상속받은 클래스를 throw 해주기
try{
//생략
} catch(InvalidObjectException e){
throw new TestException(e.getMessage());
} catch(Exception e){
throw new TestException(e.getMessage());
}
public class TestException extends RuntimeException {
private final ErrorCode errorCode;
public TestException(String message, ErrorCode errorCode) {
super(message);
this.errorCode = errorCode;
}
public TestException(ErrorCode errorCode) {
super(errorCode.getMessage());
this.errorCode = errorCode;
}
public ErrorCode getErrorCode() {
return errorCode;
}
}
2. 한 클래스 내 @Transaction이 설정되어있지 않은 메소드에서 @Transaction이 설정된 메소드를 호출할 경우
spring에서 @Transactional은 인스턴스에서 처음으로 호출하는 메서드나 클래스의 속성을 따라가게 되어서 동일한 class안에 상위 메소드에 @Transactional이 없으면 하위에 선언되어 있다하더라도 전이되지 않는다.
@Transactional 아래와 같이 수정하거나 class 또는 bean을 분리한다.
//수정 전
public class TestService() {
public void test1() {
test2();
}
@Transactional
public void test2() {
//생략
}
}
//수정 후
public class TestService() {
@Transactional
public void test1() {
test2();
}
public void test2() {
//생략
}
}
3. 메소드가 private일 경우
private이면 @Transactional이 적용되지 않는다. public으로 변경하자!
'개발 > Web' 카테고리의 다른 글
[Spring] Spring Boot Admin 사용하기 - Log, Login 적용 (0) | 2022.01.25 |
---|---|
[Web] XFF - Load balancers 혹은 Proxy 환경에서 Client IP 가져오기 (0) | 2022.01.20 |
[Web] redirect시 데이터 전달하는 방법 - RedirectAttributes (0) | 2022.01.07 |
[Web] PRG 패턴 (Post - Redirect - Get) (2) | 2022.01.07 |
[JBoss] 로깅 문제, 자체적으로 사용하는 로그 라이브러리 제외하기 (0) | 2021.12.31 |
댓글