티스토리 뷰

프로그램상에서 트랜젝션을 맘대로 커밋(commit), 롤백(rollback) 할 수 있는 방법을 알아보자.

MySQL 에서 테스트 테이블 하나 만들어서 하면된다. 난 컬럼 2개뿐인 단순한 테이블을 만들고 첫번째 컬럼에는 PK 를 걸었다.

 

 컬럼

 데이터타입

 PK 여부
 aaa  varchar(10)  O
 bbb  varchar(10)

 X

 

 

 

우선 아래의 예제를 보자.

package com.spring.sample;

import java.util.HashMap;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

@Component
public class ExampleService implements Service {
	
	@Autowired
	private SqlSession sqlSession;
	
	private Log log = LogFactory.getLog(getClass());
	
	public String getMessage() throws Exception {
	
		HashMap<String, String> input = new HashMap<String, String>();
		input.put("aaa", "AIG");
		
		this.sqlSession.insert("SqlSampleMapper.insertTable01", input);
		
		
		input.put("aaa", "AIG");
		this.sqlSession.insert("SqlSampleMapper.insertTable01", input);
		
		return null;
	}
}

 

이런 소스가 있다고 하자. 같은 쿼리(SqlSampleMapper.insertTable01)를 사용하고 있고, 그 쿼리는 단순한 insert 문이다. 

(2012/08/05 - [개발/java] - [Spring] MyBatis 로 MySQL 연동하기 - 2. 스프링 설정파일 의 매퍼파일 참고)

이런식으로라면 duplication 에러가 나기 마련이다. 다시 말해서 두개의 쿼리중 앞에건 성공하지만, 두번째 쿼리가 중복키로 에러가 발생한다. 데이터는 어떻게 들어갔을까. 조회해보면 AIG 값이 들어가 있다. 이건 autocommit 설정이 기본이라는 이야기다.

 

아마 대부분의 프로젝트는 트랜젝션 단위로 묶여 비지니스 처리가 되고 있고, 심지어 연동거래로 인한 여러건의 거래를 하나의 트랜젝션으로 묶어 처리하거나, 각각의 트랜젝션으로 쪼개서 처리(commit, rollback) 하는게 가능해야 할 것이다. 이런식의 autocommit 은 사용될 곳이 별로 없다. 다른 방법으로 선언적 트렉젝션 처리라고 해서 <tx:...> 식으로 트랜젝션을 정의해서 사용할 수 있게 스프링에서 제공하고 있는데 읽어봐도 내가 원하는 건 아니었다.

 

If you want to control your transactions programmatically please refer to chapter 10.6 of the Spring reference manual. This code shows how to handle a transaction manually using the PlatformTransactionManager described in section 10.6.2.

 

스프링에서는 트랜젝션을 프로그램상에서 제어하고 싶은 경우 Spring reference 메뉴얼 10.6 장을 참고하라고 한다. 그래서 그걸 토대로 만들어 본 트랜젝션 처리 예제 이다.

package com.spring.sample;

import java.util.HashMap;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

@Component
public class ExampleService implements Service {
	
	@Autowired
	private SqlSession sqlSession;
	
	@Autowired
	private DataSourceTransactionManager transactionManager;
	
	private Log log = LogFactory.getLog(getClass());
	
	public String getMessage() throws Exception {
		DefaultTransactionDefinition def = new DefaultTransactionDefinition();
		def.setName("example-transaction");
		def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
		
		TransactionStatus status = transactionManager.getTransaction(def);
		
		
		try {
			HashMap<String, String> input = new HashMap<String, String>();
			input.put("aaa", "AIZ");
			this.sqlSession.insert("SqlSampleMapper.insertTable01", input);
			
			
			input.put("aaa", "AIZ");
			this.sqlSession.insert("SqlSampleMapper.insertTable01", input);

			
		} catch (Exception e) {
			// TODO: handle exception
			transactionManager.rollback(status);
			throw e;
		}

		transactionManager.commit(status);
		return null;
	}
}

 

 

사실 레퍼런스 매뉴얼을 봐도 그리 자세히 설명은 나와 있지 않다.. 뭐 달랑 코드 몇줄일뿐..

기본적으로 transactionManager Bean 객체를 이용한다. 그리고 DefaultTransactionDefinition 객체에 트랜젝션 속성을 정의하여 TransactionStatus 객체를 얻어낸다. 그래서 try catch 문으로 commit 과 rollback 처리구문을 넣는다.

close 함수같은 건 없으니 사용하려고 애쓰지 않으셔도 된다.

 

처리해보면 알겠지만 2번째 쿼리가 중복키로 에러발생하므로 롤백처리가 나게 된다. 결국 저장되 있는 AIZ 값은 없다.

어쨋든 이렇게라도 트랜젝션을 맘대로 관리할 수 있게 된다.






반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함