스프링/6. 스프링 DB-2

46. 트랜잭션과 예외

sdafdq 2023. 10. 16. 01:47

Default는 런타임예외 발생 시 롤백,

체크예외 발생 시 커밋임.

 

@SpringBootTest
public class RollbackTest {
    @Autowired
    RollbackService service;

    @Test
    void runtimeException(){
        assertThatThrownBy(()->service.runtimeException())
                .isInstanceOf(RuntimeException.class);
    }

    @Test
    void checkedException(){
        assertThatThrownBy(()->service.checkedException())
                .isInstanceOf(MyException.class);
    }

    @Test
    void rollbackFor(){
        assertThatThrownBy(()->service.rollbackFor())
                .isInstanceOf(MyException.class);
    }

    @TestConfiguration
    static class RollbackTestConfig{
        @Bean
        RollbackService rollbackService(){
            return new RollbackService();
        }
    }
    @Slf4j
    static class RollbackService{
//        런타임 예외 : 롤백
        @Transactional
        public void runtimeException(){
            log.info("call runtimeException");
            throw new RuntimeException();
        }

//        체크예외 : 커밋
        @Transactional
        public void checkedException() throws MyException {
            log.info("call checkedException");
            throw new MyException();
        }

//        체크예외를 rollbackFor 지정 : 롤백됨
        @Transactional(rollbackFor = MyException.class)
        public void rollbackFor() throws MyException {
            log.info("call rollbackForException");
            throw new MyException();
        }

    }

    static class MyException extends Exception{

    }
}

먼저 그냥 트랜잭션을 사용하며 예외를 날리는 클래스를 생성하고, 그것을 호출.

 

그리고, application.properties에

logging.level.org.springframework.jdbc.datasource.DataSourceTransactionManager = DEBUG
logging.level.org.springframework.orm.jpa.JpaTransactionManager=DEBUG

대충 TransactionManager가 남기는 DEBUG 로그를 보는거임.

이러면 이제 커밋하는지 롤백하는지 로그 볼 수 있음.

근데 Transactional Complete 이후에 rollback, commit 등의 여부가 나오는 데, 

이거는 로그만 순서가 이런 거고, 롤백, 커밋 이후에 Transactional Complete가 맞음.

 

테스트 코드 보면 그냥 예외 받게만 해놨지 따로 트랜잭션 매니저 뭐 검사해서 조건 만들어서 커밋인지 롤백인지 확인하지는 않음. (트랜잭션매니저 또한 빈으로 등록되는 것일 터이니 주입받아서 사용하면 됨. PlatformTransactionManager가 인터페이스임. TransactionManager가 이미 있어서 Platform 붙였다고 했었음.)

 

그런 테스트코드는 잘 안만드는지 복잡할 거 같다고 함.

 

여튼 예외에 따라 확인 결과

런타임 예외는 항상 롤백,

체크예외는 커밋,

rollbackFor 옵션 준 @Transactional은 당연히 롤백 되었음.

(물론 그 반대인 noRollbackFor도 있음.)

 

?

왜 체크예외이면 커밋을 할까.

다음장에 설명.