1. 스프링의 트랜잭션 지원
- 스프링은 코드 기반의 트랜잭션 처리(Programmatic Transaction) 뿐만 아니라 선언적 트랜잭션(Declarative Transaction)을 지원하고 있다. 스프링이 제공하는 트랜잭션 템플릿 클래스를 이용하거나 설정 파일, 어노테이션을 이용해서 트랜잭션의 범위 및 규칙을 정의할 수 있다.
2. 선언적 트랜잭션 처리
- 선언적 트랜잭션은 설정 파일이나 어노테이션을 이용해서 트랜잭션의 범위, 롤백 규칙 등을 정의
- 다음과 같은 2가지 방식으로 정의
1) <tx:advice> 태그를 이용한 트랜잭션 처리
2) @Transactional 어노테이션을 이용한 트랜잭션 설정
다음 소스로 예를 들어보겠다.
/**
* 사업부 정보 등록,수정
* @param map
* @return
* @throws Exception
*/
@Transactional
public int saveDivisionData(Map<String, Object> map) throws Exception {
int cnt = companyDAO.saveDivisionData(map);
// 사업부 수정이 정상적으로 처리되면 대상 사업부를 확산대상으로 지정한다.
if(cnt == 1){
companyDAO.saveExtensionTarget(map);
}
return cnt;
}
@Transactional을 써주는 이유?
companyDAO.saveDivisionData 에서 처리한 쿼리문이 정상적으로 완료가 되고, companyDAO.saveextensionTarget 에서 처리 도중 에러가 났을 때
companyDAO.saveDivisionData 에서 처리한 쿼리를 자동 rollback 해주기 위해 사용된다.
만약 저 어노테이션을 써주지 않는다면, 위에꺼는 정상적으로 완료가 되었기 때문에 직접 save한 division 데이터를 복구 시켜놔야함...
- 인터페이스를 구현한 클래스로 선언된 빈은 인터페이스 메소드에 한해서 트랜잭션이 적용됨
- 인터페이스에 붙은 @Transactional 선언은 인터페이스 내의 모든 메소드에 적용됨
- 동시에 메소드 레벨에도 @Transactional을 지정할 수 있다. 메소드 선언 > 인터페이스 선언
- 클래스의 @Transactional > 인터페이스의 @Transactional
- @Transactional 적용 대상은 미리 결정하고 애플리케이션 안에서 통일하는게 좋음. 인터페이스와 클래스 양쪽에 불규칙하게 @Transactional이 혼용되는 건 바람직하지 못함
context-transaction.xml 파일에 아래와 같이 선언
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="select*" read-only="true" />
<tx:method name="list*" read-only="true" />
<tx:method name="retrieve*" read-only="true" />
<tx:method name="get*" read-only="true" />
<tx:method name="find*" read-only="true" />
<tx:method name="view*" read-only="true" />
<tx:method name="*Move" read-only="true" />
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="create*" propagation="REQUIRED"/>
<tx:method name="merge*" propagation="REQUIRED"/>
<tx:method name="execute*" propagation="REQUIRED"/>
<tx:method name="excel*" propagation="REQUIRED"/>
<tx:method name="CALL" propagation="REQUIRED"/>
<tx:method name="*" rollback-for="Exception"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="requiredTx" expression="execution(* com.????.??..impl.*Impl.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="requiredTx" />
</aop:config>
<tx:annotation-driven transaction-manager="txManager"/> // @Transactional을 사용할 때 필요한 설정은 다음 한 줄 뿐이다. <tx:annotation-driven> 태그는 등록된 빈 중에서 @Transactional이 붙은 클래스나 인터페이스 또는 메소드를 찾아 트랜잭션 어드바이스를 적용해 준다.
참고: http://snoopy81.tistory.com/335