1. Checked Exception일 경우
사실 이 항목에 대한 설명을 위해 어제 java의 error와 exception에 대해 포스팅을 했다.
Checked Exception이 뭔지 모른다면 먼저 아래 포스팅을 보고 오는 것을 추천!
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 |
댓글