JAVA Spring Framework에서는 iBatis를 사용하여 DB에 접근하기 위해 SqlMapClientDaoSupport라는 DAO클래스를 사용한다.
그리고 SqlMapClientDaoSupport클래스는 실질적인 데이터 조작 및 접근을 위해 다음의 2가지 형태의 메서드를 제공하는데 그것이
- getSqlMapClientTemplate()
- getSqlMapClient()
이다.
이 둘은 DB의 실질적인 데이터에 접근하여 처리하는 것에는 변함이 없지만 동작 처리 방식에는 차이가 있다.
예를 들어 둘다 동일한 메서드를 가지고 있고 INSERT하는 동작을 처리하는 코드를 작성했다고 한다면 두 메서드는 동일하게 iBatis의 INSERT를 처리하나 트랜젝션에 차이가 있다.
getSqlMapClientTemplate().insert();
요청한 INSERT를 즉시 실행하며, 바로 트랜젝션 완료 처리(COMMIT)가 된다. 즉, INERT쿼리에 대해 자동으로 트렌젝션 처리가 된다는 것이다.
getSqlMapClient().insert();
사용자가 명시적으로 최종 트랜젝션 처리를 할 때까지는 트렌젝션 완료 처리가 되지 않는데 이런 방식을 로컬 트랜젝션(Local Transaction)이라고 하며 일괄 처리(Batch Procession) 기법이라고 한다.
좀 더 쉽게 알아보기 위해 예제를 봐보자.
//Example1 - getSqlMapClientTemplate
for (i = 0; i < 100; i++) {
getSqlMapClientTemplate().insert();
}
//Example2 - getSqlMapClient
getSqlMapClient().startTransaction();
getSqlMapClient().startBatch();
for (i = 0; i < 100; i++) {
getSqlMapClient().insert();
}
getSqlMapClient().executeBatch();
getSqlMapClient().endTransaction();
두개의 쿼리를 for문으로 수행시켰는데 여기서 91번째에 예상치 오류가 발생했고 91번째 요청을 처리하지 못하고 Exception에러를 발생했다고 가정해보면
예제1의 경우, INSERT() 요청마다 자동 트랜젝션 완료처리가 되므로, 90번까지의 INSERT의 요청이 DB에 정상적으로 COMMIT된다.
하지만 예제2의 경우, INSERT()요청이 실행 된 후, 자동 트랜젝션 완료처리가 되지 않으므로 사용자가 명시적으로 for문 시작과 끝에 startTransaction()과 endTransaction()을 호출하였기에 90번까지 수행된 상태에서 에러가 발생하여 endTransaction()이 정상적으로 호출되지 않았고 그 상태로 for문이 종료되었기에 startTransaction() 이후에 실행된 모든 INSERT()요청이 취소되고 ROLLBACK 된다.
즉, 단하나의 INSERT요청도 처리되지 않은 상태다.
또한, 100번이 성공적으로 수행되었다고 한다면 예제1은 100번의 쿼리 실행과 100번의 COMMIT가 수행되겠지만,
예제2은 100번의 쿼리 실행과 1번의 COMMIT만 수행된다.
※ 좀 더 쉬운 예시로 회원 가입으로 들자면
1. 회원 정보를 DB에 기록하고
2. 회원 가입 축하 포인트를 DB에 기록하며
3. 가입과 동시에 자동 로그인 후 로그인 로그를 DB에 기록하는 3개의 쿼리를 만들었다고 가정해보자.
이 3개의 쿼리는 동시에 모두 처리되어야 하며 일부만 수행되어서는 안되며 단 하나의 쿼리라도 오류가 발생하는 경우에는 이미 실행된 쿼리를 모두 ROLLBACK하고 사용자에게 안내메시지를 띄어야한다.
이러한 경우라면 반드시 getSqlMapClient()의 트렌젝션 기능을 써야한다.