Chapter5. Spring 트랜잭션 트랜잭션은 Atomicity, Consistency, Isolation, Durability 네 가지 속성을 가진다. Atomicity (원자성) 트랜잭션 내에 있는 모든 작업이 완료되거나 모든 작업이 완료되지 않아야 한다. Consistency (일관성) 트랜잭션 중에 오류 없이 유효한 데이터만 데이터베이스에 저장되어야 한다. Isolation (격리성) 트랜잭션 중에 변경된 내용이 트랜잭션이 완료되기 전까지 다른 트랜잭션에 영향을 미쳐서는 안 된다. Durability (지속성) 트랜잭션이 완료된 경우 시스템 고장이나 네트워크 에러 등으로 데이터가 유실되지 않고 정상적으로 기록되어야 한다. TransactionDefinition.java package org.springframework.transaction;
1. 문제점 및 해결 방법
4장 게시판 예제에서 BOARD 테이블과 BOARDFILE 테이블에 데이터가 추가되는데, BOARDFILE 테이블에 데이터를 추가하는 중에 에러가 발생하면 BOARD 테이블에 추가되었던 데이터가 롤백되지 않으며 BOARDSEQUENCE, BOARDFILESEQUENCE 테이블의 값 또한 롤백되지 않는다.
Spring JDBC를 기반으로 개발할 경우 개발자들은 Connection 인스턴스에 직접적으로 접근하지 않기 때문에 Connection 인스턴스를 기반으로 트랜잭션을 처리하는 것이 힘들어진다.
Spring 프레임워크는 이와 같은 문제점을 해결하기 위하여 트랜잭션을 처리하기 위한 새로운 API를 제공하고 있다.
Spring 프레임워크는 트랜잭션을 처리하기 위한 방법으로 소스 코드 내에서 프로그램적으로 처리하는 방법과 빈 설정 파일에서 선언적으로 처리하는 두 가지 방법을 지원한다.
2. Spring 트랜잭션 기본
트랜잭션 지원 핵심 API : PlatformTransactionManager, TransactionDefinition, TransactionStatus
즉, 트랜잭션 내의 작업 중 하나라도 에러가 발생하면 트랜잭션 내의 모든 작업이 롤백(Rollback) 되어야 한다.
▶ TransactionDefinition : 트랜잭션 제어 정의
- 트랜잭션의 네 가지 속성(ACID) 중 개발자들이 제어 가능한 부분(트랜잭션 전달(Propagation), timeout, read-only 상태, 격리셩(Isolation) 레벨의 네 가지 속성)을 추상화
public interface TransactionDefinition {
// 트랜잭션이 실행되어야 하는 범위에 대한 제어와
// 여러 개의 트랜잭션이 어떻게 상호작용하는지에 대하여 결정하는 것이 가능하다.
int getPropagationBehavior();
// 실행하는 트랜잭션의 격리 레벨을 지정하는 것이 가능하다.
// 즉, 현재 트랜잭션 내에서 변경된 데이터가 다른 트랜잭션에 반영될지에 대한 레벨을 결정하는 것이 가능하다.
int getIsolationLevel();
// 실행하는 트랜잭션이 시작해서 종료할 때까지의 시간을 초 단위로 제어하는 것이 가능하다.
int getTimeout();
// 실행하는 트랜잭션이 read-only 상태인지 아닌지를 결정하는 것이 가능하다.
boolean isReadOnly();
}
격리 레벨(Isolation Level)과 전달 행위(Propagation Behavior)는 트랜잭션이 어떻게 동작해야 되는지를 결정하기 위하여 여러 개의 값으로 나뉘어진다.
트랜잭션 격리 레벨 (Isolation Level)
격리 레벨 (Isolation Level) |
상세 설명 |
TransactionDefinition. |
개별적인 PlatformTransactionManager를 위한 디폴트 격리 레벨 |
TransactionDefinition. |
격리 레벨 중 가장 낮은 격리 레벨이다. 이 격리 레벨은 다른 Commit 되지 않은 트랜잭션에 의해 변경된 데이터를 볼 수 있기 때문에 거의 트랜잭션의 기능을 수행하지 않는다. |
TransactionDefinition. |
대개의 데이터베이스에서의 디폴트로 지원하는 격리 레벨이다. 이 격리 레벨은 다른 트랜잭션에 의해 Commit 되지 않은 데이터는 다른 트랜잭션에서 볼 수 없도록 한다. 그러나 개발자들은 다른 트랜잭션에 의해 입력되거나 수정된 데이터는 조회할 수 있다. |
TransactionDefinition. |
ISOLATION_READ_COMMITTED 보다는 다소 엄격한 격리 레벨이다. 이 격리 레벨은 다른 트랜잭션이 새로운 데이터를 입력했다면 새롭게 입력된 데이터를 조회할 수 있다는 것을 의미한다. |
TransactionDefinition. |
가장 많은 비용이 들지만 신뢰할 만한 격리 레벨을 제공하는 것이 가능하다. 이 격리 레벨은 하나의 트랜잭션이 완료된 후에 다른 트랜잭션이 실행하는 것처럼 지원한다. |
전달 행위 (Propagation Behavior) |
상세 설명 |
TransactionDefinition. |
이미 하나의 트랜잭션이 존재한다면 그 트랜잭션을 지원하고, 트랜잭션이 없다면 새로운 트랜잭션을 시작한다. |
TransactionDefinition. |
이미 트랜잭션이 존재한다면 그 트랜잭션을 지원하고, 트랜잭션이 없다면 비-트랜잭션 현태로 수행한다. |
TransactionDefinition. |
이미 트랜잭션이 존재한다면 그 트랜잭션을 지원하고, 활성화된 트랜잭션이 없다면 예외를 던진다. |
TransactionDefinition. |
언제나 새로운 트랜잭션을 시작한다. 이미 활성화된 트랜잭션이 있다면 일시 정지한다. |
TransactionDefinition. |
활성화된 트랜잭션을 가진 수행을 지원하지 않는다. 언제나 비-트랜잭션으로 수행하고 존재하는 트랜잭션은 일시 정지한다. |
TransactionDefinition. |
활성화된 트랜잭션이 존재하더라도 비-트랜잭션적으로 수행한다. 활성화된 트랜잭션이 존재한다면 예외를 던진다. |
TransactionDefinition. |
활성화된 트랜잭션이 존재한다면 내포된 트랜잭션으로 수행된다. 작업 수행은 TransactionDefinition.PROPAGATION_REQUIRED 으로 세팅된 것처럼 수행된다. |
TransactionStatus.java |
package org.springframework.transaction; |
PlatformTransactionManager.java |
package org.springframework.transaction; |
applicationContext-jdbc.xml - 선언적 트랜잭션 설정 |
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> |
applicationContext-user.xml - 사용자 관리 프로젝트에 트랜잭션을 처리하는 부분 |
<bean id="userServiceTarget" class="net.javajigi.user.service.UserServiceImpl"> |
applicationContext-board.xml - 자료실 게시판에 트랜잭션을 처리하는 부분 |
<bean id="boardServiceTarget" class="net.javajigi.board.service.BoardServiceImpl"> |
Spring 프레임워크에서 선언적으로 트랜잭션을 처리할 때 트랜잭션 속성을 정의하는 방법 | |
빈 설정 파일에서 트랜잭션 속성을 설정할 때 위와 같은 규칙으로 작성하면 된다. 위 각 항목들에 대하여 살펴보면 다음과 같다. * 전달 행위 : 필수 값으로 전달 행위 (Propagation Behavior) 표의 값 중 하나를 사용할 수 있다. * 격리 레벨 : 선택 값으로 트랜잭션 격리 레벨 (Isolation Level) 표의 값 중 하나를 사용할 수 있다. * readOnly 유무 : 선택 값으로서 실행하는 트랜잭션이 읽기 전용일 경우에 사용 가능하다. 일반적으로 트랜잭션 내에서 SELECT 쿼리만을 실행하는 경우이 속성을 사용한다. * Rollback 규칙 : Spring 프레임워크 트랜잭션의 디폴트 설정은 RuntimeException 이 발생하는 경우에는 Rollback, CheckedException 이 발생하는 경우에는 Commit 되도록 하고 있다. 그러나 트랜잭션의 속성을 지정할 때 Rollback 규칙을 이용하여 디폴트 설정을 변경하는 것이 가능하다. Rollback 규칙에서 마이너스(-)로 시작하는 Exception 에 대해서는 무조건 Rollback, 플러스(+)로 시작하는 Exception 에 대해서는 무조건 Commit 되도록 규칙을 변경할 수 있다. ex) PROPAGATION_REQUIRED, ISOLATION_SERIALIZABLE, -net.javajigi.user.PasswordMismatchException |
applicationContext-user.xml |
<bean id="userService" class="net.javajigi.user.service.UserServiceImpl"> |
applicationContext-board.xml |
<bean id="boardService" class="net.javajigi.board.service.BoardServiceImpl"> |
applicationContext-transaction.xml |
<beans> |
출처 : http://kr.blog.yahoo.com/i056695/1030.html?p=3&pm=l&t=1&tc=50&tt=1213170497
SSISO Community