SQLException과 스프링 트랜잭션 질문입니다.

2014-07-07 17:29

최근까지 참여한 프로젝트에

Service계층 클래스 메소드에 @Transactional선언을 하였습니다. RunitmeException의 경우 트랜잭션이 롤백이 되고 SQLException의 경우 Checkd Exception이기에 롤백이 되지 않는걸로 알고있습니다.

그럼 다음과 같은 코드에

@Transactional(propagation=Propagation.REQUIRED)	
public ModelAndView xxxxInsert(HttpServletRequest request) throws SQLException{
	
	xxxxDao.insert1(param);
	xxxxDao.insert2(param);
}

서비스 계층 클래스 메소드에서 두번의 insert를 했고 두번째 insert에서 SQLException이 일어났다면 롤백이 되지 않기에 첫번째 insert에 대한 정보는 DB에 입력이 되어있는게 맞나요?

그리고 해결책은 rollback-for="Exception" 이렇게 해야 되는게 맞는지요?

다음은 찾은 자료인데 확신이 서지 않네요 http://stackoverflow.com/questions/7125837/why-does-transaction-roll-back-on-runtimeexception-but-not-sqlexception

4개의 의견 from SLiPP

2014-07-08 09:39

정확히 알고 계시네요.

SQLException은 Checked Exception이나 Spring Transaction에서 자동으로 Rollback을 하지 않아요. 이 같은 경우 말씀하신 것처럼 rollback-for 설정을 해주셔야 됩니다.

Rollback의 경우 rollback-for="Exception"와 같이 설정할 수도 있겠지만 그 보다는 SQLException으로 한정하는 것이 더 좋지 않을까 생각합니다. Exception으로 지정할 경우 기대하지 않은 곳에서 Rollback이 될 수 있으니까요?

그런데 일반적으로 Spring에서 제공하는 Spring JDBC나 MyBatis와 같은 연동 API를 쓸 경우 SQLException이 발생하지 않고 RuntimeException이 발생할텐데 SQLException이 발생하는 구조는 의외네요. 정말 SQLException이 발생하는 구조라면 DAO 내부를 좀 공유해 주셔도 좋겠네요.

2014-07-08 14:08

자바지기님 답변 감사합니다. 말씀대로 IBatis, MyBatis에서는 RuntimeException이 발생하더군요 그리고 SqlMapClientTemplate에서는 throws DataAccessException 발생시키구요

SqlMapClientTemplate에서는 throws DataAccessException를 던졌는데 프로젝트에서는 그걸 받아서 throws SQLException으로 포장했구요

지금은 throws SQLException을 throws Exception 변환했습니다.

감사합니다 ^^

2014-07-08 14:12

@록키정신 Spring 프레임워크에서는 SQLException과 같이 Checked Exception의 남용으로 인한 페해를 줄이고자 DataAccessException과 같은 Runtime Exception으로 포장해서 API를 제공하고 있습니다.

이런 상태에서 DataAccessException을 다시 SQLException으로 포장하는 이유가 있나요? 최근의 흐름은 정말 필요하지 않은 곳에서는 가능하면 Checked Exception을 사용하지 않는 방향으로 진행되고 있는데요. 현재 구조를 다시 한번 검토해 보는 것이 좋을 듯 합니다.

의견 추가하기

연관태그

← 목록으로