본문 바로가기

TroubleShooting/Spring

Spring 에서 트랜잭션 관리

728x90

스프링은 트랜잭션 처리를 위해 선언적(declarative) 트랜잭션 관리와 프로그램적(programmatic) 트랜잭션 관리 방법을 제공한다.

* declarative 트랜잭션

콘택스트 파일에 <tx:advice> 를 이용하거나 <tx:annotation-driven> 를 사용하는 방법. 둘다 트랜잭션 매니져(transactionManager) 를 스프링 빈으로 등록하지만 <tx:advice> 는 <aop> 설정이 또 필요하다. <tx:annotation-driven> 은 트랜잭션 관리가 필요한 클래스나 메소드에 직접 @Transactional 애너테이션만 추가해주면 설정이 끝난다. <tx;advice> 는 여러 옵션이 들어갈 수 있기때문에 사용할 환경에 맞춰서 선택하면 될거 같다. 두 방식다 스프링 AOP 가 동작하기 하지만 애너테이션 방식이 필요한 곳에만 애너테이션을 추가하면 되기 때문에 편해보이긴 한다.


* @Transactional 애노테이션 방식

- 콘택스트 파일에서 트랜잭션 매니져 등록(JDBC 를 사용하기 때문에 DataSourceTransactionManager 를 이용)


 

- 예제 코드

	@Override
	@Transactional
	public void testTrac(int id) {
		String sql = "delete from ii where id = ?";
		jdbcTemplate.update(sql, id);

		sql = "delete from jj where idd = ?";
		jdbcTemplate.update(sql, id);
	}

ii, jj 테이블은 둘다 id 라는 컬럼을 가지고 있다. 예제에서는 jj 테이블의 idd 라는 존재하지 않는 컬럼의 값을 삭제해서 일부러 오류를 발생시킨다. 실제로 실행하면 메소드 전체가 트랜잭션이 되어서 첫번째 쿼리문이 실행될때는 ii 테이블의 값이 삭제가 안되고 두번째 쿼리문이 실행되고 메소드가 끝났을때 테이블의 값들이 삭제된다.


* Programmatic 트랜잭션 처리

프로그램 코드 안에 직접 트랜젹션 처리를 넣는 방식인데, 사용할 곳이 많이 없다면 이용해도 될듯하다.

DefaultTransactionDefinition def = new DefaultTransactionDefinition();
// explicitly setting the transaction name is something that can only be done programmatically
def.setName("SomeTxName");
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

TransactionStatus status = txManager.getTransaction(def);
try {
  // execute your business logic here
}
catch (MyException ex) {
  txManager.rollback(status);
  throw ex;
}
txManager.commit(status);

관련 링크 :

http://docs.spring.io/spring/docs/3.0.x/reference/transaction.html

http://stackoverflow.com/questions/18528876/spring-aop-vs-transactional-annotation