Spring & Spring Boot

[Spring&Spring Boot] @Transaction, rollback이 안될 때가 있다??

김먼저 2023. 3. 28. 16:17

@Transaction 어노테이션을 걸고 service 로직을 구현 및 테스트를 진행하다가

 

예외가 발생했으나 DB에는 데이터가 저장되는 기이한 현상을 겪어 (주니어라 그래요 이해좀)

 

다른 분들도 혹시 겪는다면 빠르게 해결되길 바라는 마음으로 글을 써봅니다.

 

 

 

Spring 프레임워크에서 @Transactional 어노테이션은 트랜잭션 관리를 쉽게 해주는 기능을 제공합니다.

 

@Transactional 어노테이션을 사용하면, 메소드가 실행될 때 트랜잭션을 시작하고,

 

메소드가 정상적으로 실행되면 트랜잭션을 커밋하고, 예외가 발생하면 롤백합니다.

 

 

 

 

제가 체크하는 로직에 예외처리를 했고 여기서 에러가 터질때마다 DB에 데이터는 저장되는데

 

로직이 진행이 안되는 문제가 발생했습니다.

 

...????  분명 난 @Transactional 어노테이션을 걸었고, 예외가 발생하여 분명 커밋이 되지 않았을텐데 저장이 되었다...??

 

 

 

 

 

@Transactional 어노테이션을 사용하여 트랜잭션을 설정했다면,

 

메서드 실행 중 예외가 발생하면 자동으로 롤백됩니다. 이는 기본 동작입니다.

 

하.지.만!!!

 

일부 예외(Exception)는 롤백이 되지 않는 Exception이 있습니다.

 

 

1.  Checked Exception : 각각 꼭 처리해서 체크해줘야하는 예외. 처리를 안해줘도 되는 예외.

 

 

 

그럼 어떤 예외일 때 롤백시켜주는걸까??

 

 

1. Unchecked Exception : 체크되지 않는 예외

ex) RunTimeException

2. Error : H/W Error

ex) OutOfMemoryError

 

 

 

그러면 Checked Exception에서 롤백을 하고싶을땐 어떻게 해야할까??

 

 

 

@Transactional(rollbackFor = xxxException.class)

 

rollbackFor 속성에 checked Exception class를 입력하면 됩니다.

 

 @Transactional(rollbackFor = BadRequestCException.class, Exception.class)
    public void setUser(Long userSeq, DTO dto) throws Exception {
    
    ...
    
        if(dto.getProjectSeq() == null) {
            throw new BadRequestCException("Project is empty.");
        }

        //중복 체크
        for(Dtos dto : abcds){
            if(!set.add(dto.getUserId())){
                throw new Exception("Duplicate ID exists.(User ID = " + userId());
            }
        }
        ...