[Spring]@Transactional에서 예외발생 시 커밋과 롤백

스프링의 트랜잭션 AOP에서는 예외의 종류에 따라 트랜잭션을 커밋하거나 롤백한다.

  • 롤백하는 경우 : RuntimeException, Error와 그 하위 예외
  • 커밋하는 경우 : Exception과 그 하위 예외 / 정상적으로 종료되는 경우(예외 미발생)
예외 구분트랜잭션
ObjectThrowableErrorLinkageError롤백
ThreadDeath롤백
.. 기타 에러롤백
ExceptionRuntimeExceptionunChecked롤백
SQLExceptionchecked커밋
… 기타 예외checked커밋

아래 예제코드를 참조하자

@SpringBootTest
public class RollbackTest {

    @Autowired
    RollbackService service;

    @Test
    @DisplayName("RuntimeException은 트랜잭션을 롤백한다.")
    void runtimeExceptionTest() {
        assertThatThrownBy(() -> service.runtimeException())
                .isInstanceOf(RuntimeException.class);
    }

    @Test
    @DisplayName("CheckedException은 트랜잭션을 커밋한다.")
    void checkedExceptionTest() {
        assertThatThrownBy(() -> service.checkedException())
                .isInstanceOf(MyException.class);
    }

    @Test
    @DisplayName("지정된 CheckedException은 트랜잭션을 롤백한다.")
    void rollbackForExceptionTest() {
        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 rollbackFor");
            throw new MyException();
        }

    }

    static class MyException extends Exception {
    }
}

You may also like...

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다