반응형

2022.03.16 - [개발/spring] - [spring] ChainedTransactionManager deprecated from boot 2.5

 

[spring] ChainedTransactionManager deprecated from boot 2.5

한 트랜젝션에서 서로 다른 DB에 update/insert 작업을 연속적으로 하게 될 때 이를 하나의 트랜젝션으로 보존할 수 있도록 스프링에서는 ChainedTransactionManager라는 클래스를 제공해주었다. 물론 이는

bangpurin.tistory.com

다중 DB의 트랜젝션 관리를 위해서 chainedTransactionManager를 사용 중에 있다.

오늘 라이브러리 수정 작업을 하면서 혹시 영향이 있을까 관련 테스트를 했는데, 중간에 exception을 던져도 rollback 되지 않고 commit이 되길래 이게 왜 안되지 싶었다.

하여 관련하여 구글링해보니 아래와 같은 글이 있었다.

1 - Change your exception to an unchecked exception (extends RuntimeException)
2 - Forces Spring to rollback a checked exception.

https://stackoverflow.com/questions/68001086/rollback-is-not-working-for-springboot-jparepository

 

Rollback is not working for Springboot JpaRepository

I have Spring Boot (v2.4.1) application with Hibernate and JpaRepository like Dao. Here is code: import javax.transaction.Transactional; @Service public class SomeService { pu...

stackoverflow.com

 

즉 checked exception인 Exception.class을 던지면 롤백이 안되고, Exception으로 롤백을 하고 싶다면 롤백 옵션을 줘야 한다는 것..

이것도 모르고 throw new Exception 이렇게 테스트를 했으니.. 당연히 안되었던 것이다..ㅎ

무튼 아래와 같이 RuntimeException을 발생시켜서 롤백이 잘 되는지 확인하였다.

@Transactional(transactionManager = Constants.CHAINED_TRANSACTION_MANAGER)
public BaseResponse resetLossMoney(ResetLossMoneyRequest req) throws Exception {
    checkExpiredDateAndSave(req.getCi());
    setChangedAndSave(req.getCi());
    if(1==1) throw new RuntimeException("test");
    insertResetLossMoneyLog(req.getCi(), GID_DEFAULT);
    return new BaseResponse();
}

 

위 내용과 별도로 트랜젝션이 잘 되는지 확인하고 싶다면 로그백에 아래를 추가하면 확인 가능하다.

<logger name="org.springframework.transaction.interceptor" level="TRACE"/>

 


 

  • 스프링 프레임워크에서는 기본적으로 Unchecked Exception(런타임 예외)이 발생하면 트랜잭션을 롤백합니다.
  • 반면, Checked Exception(체크드 예외)은 기본적으로 트랜잭션을 롤백하지 않습니다. 이는 Checked Exception이 비즈니스 로직 내에서 예외적인 상황으로 처리될 수 있기 때문입니다.
  • checked exception에서도 롤백이 필요하다면 rollbackFor을 활용하면 된다.
@Transactional(rollbackFor = IOException.class)
public void performTransaction() throws IOException {
    repository.save(new Entity());

    // Checked Exception 발생
    if (true) {
        throw new IOException("Checked Exception");
    }

    repository.save(new Entity());
}

 

  •  특정 Unchecked Exception에 대해서는 롤백을 원하지 않을 때 noRollbackFor 속성을 사용합니다.

왜 기본적으로 Unchecked Exception에 대해서만 롤백할까?

  1. 비즈니스 로직과의 분리: Checked Exception은 비즈니스 로직 내에서 발생할 수 있는 예외적인 상황을 나타내며, 이를 비즈니스 로직의 일부로 처리하는 경우가 많습니다. 반면, Unchecked Exception은 예외적 상황이 아니라 코드의 오류나 논리적 문제를 나타내므로 트랜잭션의 롤백이 필요합니다.
  2. 복구 가능성: Checked Exception은 복구 가능한 예외로 간주되어, 개발자가 예외를 처리하여 정상적인 흐름으로 돌아갈 수 있다고 판단할 수 있습니다. Unchecked Exception은 복구가 불가능한 예외로 간주되어 트랜잭션을 롤백하는 것이 합리적입니다.
728x90
반응형

+ Recent posts