탑크리에듀교육센터(www.topcredu.co.kr)제공
스프링프레임워크 & 마이바티스(Spring Framework, MyBatis)
20번째 자료입니다. 참고하시어 많은 도움되셨길 바랍니다.
교육 및 수강문의/기타문의사항은 홈페이지(www.topcredu.co.kr)를 통하여 하실 수 있습니다.^^
1. 스프링프레임워크 & 마이바티스
(Spring Framework, MyBatis)
5-4. 스프링 선언적 트랜잭션 관리
AOP를 이용하여 선언적 트랜잭션을 설정하는 방법에는 2가지가 있다.
1. XML Configuration - 스프링의 빈 설정파일에 <tx:advice> <aop:config> 등의 태그를 사용하
여 설정.
2. Transactional Annotation - 해당 메소드에 @Transactional Annotation을 추가하여 설
정.(@Transactional)
5-4-1. 스프링 선언적 트랜잭션 관리 – XML 설정방식
Spring2.0 이상에서 tx 스키마에 정의된 <tx:advice> 엘리먼트에 의해 Transaction의 어드바이
스를 쉽게 구현할 수 있다.
아래와 같이 XML 설정 파일에 spring-aop-4.X.xsd , spring-tx-4.X.xsd를 추가해야 한다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
2. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-
4.2.xsd">
…
</beans>
Spring AOP가 포인트컷 정의를 위해 AspecJ 포인트컷 표현식을 사용하므로 AspectJ 위버 지
원라이브러리를 클래스 패스에 추가해야 한다. 메이븐을 사용한다면 아래 의존 라이브러리를
pom.xml에 추가한다.
<!-- AspectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
tx 네임스페이스에서 tx:advice가 가장 중요한데 사용예는 다음과 같다. 또한 스프링 AOP가
프록시 기반이므로 트랜잭션이 적용될 메소드는 public으로 선언되어야 한다.
<tx:advice id=“txAdvice” transaction-manager=“transactionManager”>
<tx:attributes>
<tx:method name=“insert*” propagation=“REQUIRED”/>
<tx:method name=“get*” propagation=“REQUIRED”read-only=“true”/>
</tx:attributes>
</tx:advice>
<bean id=“transactionManager”
class=“org.springframework.jdbc.datasource.DataSourceTransactionManager”>
<property name=“dataSource” ref=“dataSource”/>
</bean>
tx:attribute에 사용되는 속성
3. name : 적용될 어드바이스에 대응되는 메소드명(필수), 와일드카드 (*)가능
isolation : 트랜잭션 격리 수준
no-rollback-for : 예외가 발생 했을때 이를 무시하고 Transaction을 롤백하지 않고 계속 진행할
예외를 지정
propagation : Transaction 전파방식 지정, 기본값:REQUIRED
read-only : 트랜잭션이 읽기 전용인지, 기본값:FALSE
rollback-for : 예외가 발생했을 때 트랜잭션을 롤백 시킬 예외들의 구체적인 타입을 콤마로 구분
하여 기술
timeout : 트랜잭션 타임아웃을 지정
<tx:advice> 자체만 보았을 때는 어느 빈에 advice가 적용되어야 하는지 알수 없다. 그러므로
Pointcut이 필요하다.( AOP의 Advice에 지나지 않는다. )
<aop:config>
<aop:advisor pointcut=“execution(* *..SpringBoardDAO.*dao(..))”
advice-ref=“txAdvice”/>
</aop:config>
5-4-1-1. 스프링 선언적 트랜잭션 관리 – XML 설정방식 예제
springtr1 이라는 이름의 spring maven Project를 생성하자.(EMP 테이블 데이터를 SELECT하고
INSERT하는 예제)
전체 프로젝트 구성은 아래와 같다.
4. STS에서
New Project Spring Legacy Project
Project Name : springtr1
Simple Projects : Simple Spring Maven
[pom.xml]
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.samples</groupId>
<artifactId>springtr1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<!-- Generic properties -->
<java.version>1.6</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-
8</project.reporting.outputEncoding>
<!-- Spring -->
<spring-framework.version>4.2.4.RELEASE</spring-framework.version>
<!-- Logging -->
<logback.version>1.0.13</logback.version>
<slf4j.version>1.7.5</slf4j.version>
9. p:username = "scott”
p:password = "tiger" />
<!-- 트랚잭션매니저 정의 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 트랚잭션용 Advice 구성 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 예외 중에서 Exception이 발생한 경우에도 롤백이 실행된다는 의미 -->
<!-- 트랚잭션 설정이 된 메소드에서 RuntimeException이 발생한 경우와 Errors가 발생한
경우에맊
기본적으로 롤백을 수행하며 그 외의 예외들은 아래와같이직접 설정한 경우에맊 롤백을 한다. -
->
<tx:method name="*"
propagation="REQUIRED” rollback-for=“Exception” />
</tx:attributes>
</tx:advice>
<!-- aop 네임스페이스를 이용한 트랙잭션이 적용될 매소드(Pointcut), 충고자(Advisor)정의
-->
<aop:config>
<aop:pointcut id="onjPointCut"
expression="execution(*
onj.edu.tr1.dao.*Dao.insert*(..))"/>
<aop:advisor advice-ref="txAdvice"
pointcut-ref="onjPointCut" />
</aop:config>
<context:component-scan base-package="onj.edu.tr1.dao"/>
<context:component-scan base-package="onj.edu.tr1.service"/>
</beans>
[OnjEmpTest.java]
package onj.edu.tr1.client;
public class OnjEmpTest {
public static void main(String[] args) throws Exception{
ApplicationContext ctx = new
ClassPathXmlApplicationContext("onjoraclejava.xml");
OnjService onjService = (OnjService)ctx.getBean("onjService");
List<Emp> list = onjService.getEmpByDeptno(10);
display(list);
10. onjService.insertEmps();
list = onjService.getEmpByDeptno(10);
display(list);
}
public static void display(List<Emp> list) {
for(Object e: list) {
System.out.print(((Emp)e).getEmpno());
System.out.print(((Emp)e).getEname());
System.out.println(((Emp)e).getDeptno());
}
}
}
[테스트 방법]
1. OnjDao.java에서 현재대로 키가 중복되는 데이터를 입력해 보라.
트랜잭션은 롤백된다.
2. 키 중복되는 부분을 주석으로 막고 실행해보라.
트랜잭션은 정상 commit 된다.
3. OnjDao.java에서 insertEmps() 메소드의 throw new Exception(); 부분 주석을 풀고 테스트
- onjoraclejava.xml에서
<tx:method name="*" propagation="REQUIRED" rollback-for="Exception"/>인 경우
트랜잭션은 롤백된다.
- onjoraclejava.xml에서
<tx:method name="*" propagation="REQUIRED“ no-rollback-for=“Exception”/>인 경우
트랜잭션은 롤백되지 않는다. 정상 commit된다.