[Spring] @Transactional 어노테이션 사용 및 예제!

트랜잭션

- 비즈니스로직에서 쪼개질 수 없는 하나의 단위작업

- 한 번에 이루어지는 작업의 단위

- 알아두면 좋은 ACID 원칙

원자성(Atomicity) 하나의 트랜잭션은 모두 하나의 단위로 처리해야 한다. A와 B 작업이 하나의 트랜잭션으로 묶여있는 경우 A는 성공, B는 실패할 경우 해당 작업단위는 실패로 끝나야한다. 즉, A,B 모두 rollback 되어야 한다는 원칙
일관성(Consistency) 트랜잭션이 성공했다면 데이터베이스의 모든 데이터는 일관성을 유지해야한다. 
격리성(Isolation) 트랜잭션으로 처리되는 중간에 외부에서의 간섭은 없어야한다.
영속성(Durability) 트랜잭션이 성공적으로 처리되면, 그 결과는 영속적으로 보관되어야 한다. 

 

실습했던 내용

- pom.xml 에 라이브러리 추가(transactional 관련만, dbcp, sqlSessionFactory 등의 내용은 생략.)

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-tx</artifactId>
  <version>${org.springframework-version}</version>
</dependency>

- root-context.xml 파일의 Namespaces 탭에서 'tx'항목 체크.

- root-context.xml 파일 소스에 TransactionManager 빈 등록

<bean id="transactionManager" 
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource"></property>
</bean>

<tx:annotation-driven/>

 

- 예제 테이블 생성

 * create table tbl_sample1( col1 varchar2(500));

 * create table tbl_sample2( col2 varchar2(50));

 > 하나의 테이블엔 500바이트, 다른 하나엔 50바이트를 줘서 대략 100정도 되는 바이트의 문자열이 들어올 경우에 대한 예제를 실행해볼것임.

 

//DAO 영역
public interface Sample1Mapper {
	@Insert("insert into  tbl_sample1 (col1) values(#{data})")
	public int insertCol1(String data);	
}
public interface Sample2Mapper {
	@Insert("insert into  tbl_sample2 (col2) values(#{data})")
	public int insertCol2(String data);	
}
// JUnit 으로 테스트
@Test
public void testLong() {
  String str="Starry\r\n"+
    "Starry night\r\n"+
    "Paint your palette blue and grey\r\n"+
    "Look out on a summer`s day";

  log.info(str.getBytes().length);

  service.addData(str);

}

위와 같은 코드가 있을 때, str 변수에는 대략 82 바이트의 길이에 해당하는 문자열이 addData() 메소드의 매개변수로 들어가면서 아래의 비즈니스 로직을 수행할 것임.

// 비즈니스 로직
@Override
public void addData(String value) {
  log.info("mapper1.................");
  mapper1.insertCol1(value);

  log.info("mapper2.................");
  mapper2.insertCol2(value);

  log.info("end.....................");
}

- 위처럼 아무 트랜잭션 처리가 되지 않은 소스는 insertCol1 에서 삽입한 내용은 DB에 반영이 되고, insertCol2 에서 삽입한 내용은 DB에 반영이 되지 않음(에러가남)

- 이유는 두 작업에 대한 트랜잭션처리를 하지 않아서!!

 

// 비즈니스 로직(트랜잭션 처리)
@Transactional
@Override
public void addData(String value) {
  log.info("mapper1.................");
  mapper1.insertCol1(value);

  log.info("mapper2.................");
  mapper2.insertCol2(value);

  log.info("end.....................");
}

- 아래와 같이 트랜잭션으로 작업단위 처리를 해놓은 경우는 두개 뿐만아니라 세개의 작업중에서도 단 하나라도 에러가나게 된다면 트랜잭션의 원칙에 따라 모두 rollback 처리되어 DB에 반영되지 않게됨.

댓글

Designed by JB FACTORY