아노테이션 드리븐 트랜잭션(@Transactional)에서 Exception을 throw할 경우 롤백(rollback)이 안됩니다.

프로그래밍/스프링프레임워크 2019. 10. 7. 00:58
반응형

스프링 프레임웍에서 데이터베이스 트랜잭션 처리를 아노테이션 드리븐으로 설정을 하면 클래스 또는 메소드에 @Transactional 아노테이션을 붙이는 것으로 트랙잭션을 처리할 수 있습니다.


이 경우 주의해야 할 것이 하나 있는데, 직접 Exception 클래스를 던져서 예외를 발생시켜서 트랜잭션을 롤백(rollback) 하려고 하면 롤백이 되지 않는다는 것입니다.


이전에 작성한 글인 "스프링프레임워크 Java config로 MyBatis 사용하기"에 댓글로 질문해 주신 내용중에 이 롤백이 되지 않는 상황에 대한 것이 있어서 답변을 해드렸는데, 글로 작성을 해 두는게 좋을 것 같아서 쓰게 되었습니다.


스프링 프레임워크 설정을 Java Config로 하면서 트랜잭션 처리는 아노테이션 드리븐으로 하는 예제 였습니다. 트랜잭션 테스트를 위해서 같은 주키를 가지는 글을 두 개 입력하는 것입니다. 두 번째 입력에서 키 중복 오류가 발생되어 모두 롤백되어 버리고 하나도 입력되지 않습니다.


@Service("boardService")

@Transactional

public class BoardServiceImpl implements BoardService {


    @Autowired

    private BoardDAO boardDao;


    @Override

    public List<BoardVO> selectBoardList() throws Exception {

        boardDao.insertBoard(3);

        boardDao.insertBoard(3);

        return boardDao.selectBoardList();

    }


}



이번에는 글을 하나 입력하고 Exception 예외를 던집니다. 결과는 예외가 발생하지만 롤백이 되지 않아서 글이 입력됩니다.


@Override

public List<BoardVO> selectBoardList() throws Exception {

    boardDao.insertBoard(3);

    // Checked 예외는 롤백이 되지 않습니다.

    throw new Exception("Exception for rollback");

}



스프링 프레임워크에서 @Transactional 아노테이션을 사용한 트랙잭션 처리에서 Checked 예외는 롤백 되지 않습니다. 이것은 스프링프레임워크가 EJB에서의 관습을 따르기 때문이라고 합니다. 그러므로 기본적으로 Unchecked 예외는 롤백이 됩니다. RuntimeException을 던지면 롤백이 된다는 것입니다.


@Override

public List<BoardVO> selectBoardList() throws Exception {

    boardDao.insertBoard(3);

    // Unchecked 예외는 롤백이 됩니다.

    throw new RuntimeException("Exception for rollback");

}



@Transactional 아노테이션의 rollbackFor 옵션을 이용하면 롤백이 되는 클래스를 지정할 수 있습니다. Exception예외로 롤백을 하려면 다음과 같이 지정하면됩니다.


@Transactional(rollbackFor = Exception.class)


여러개의 예외를 지정할 수도 있습니다.


@Transactional(rollbackFro = {RuntimeException.class, Exception.class})



추가적으로 특정 예외가 발생하면 롤백이 되지 않도록 지정하는 방법입니다.


@Transactional(noRollbackFor={IgnoreRollbackException.class})



@Transactinal 아노테이션의 기본설정은 다음과 같습니다.


트랜잭션 전파 설정 : Propagation.REQUIRED (실행중인 트랜잭션 컨텍스트가 있으면 그 트랜잭션 내에서 실행고, 없으면 새로 트랜잭션을 생성합니다.)


트랜잭션 고립 레벨 : Isolation.DEFAULT (데이터베이스 설정을 따릅니다.)


읽기전용 : false (읽기/쓰기가 기본값입니다.)


타임아웃 : -1 (타임아웃되지 않습니다.)


예외에 따른 롤백처리는 Checked 예외는 롤백되지 않고, Unchecked 예외는 롤백됩니다.



반응형

댓글을 달아 주세요

  • 홍길동 2020.05.22 20:55  댓글주소  수정/삭제  댓글쓰기

    저는 throw new Exception(); 할 때 롤백이 잘 되는데 왜 일까요? 스프링부트2 사용중입니다

    • pentode 2020.06.06 23:26 신고  댓글주소  수정/삭제

      음. 왜그럴까요? 위글은 @Transactinal 아노테이션을 사용하여 트랜잭션을 처리할 경우 입니다. 혹시 다른 방식으로 트랜잭션을 처리해서 그런게 아닐까요?