스프링프레임워크 & 마이바티스
(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
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에 사용되는 속성
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하는 예제)
 전체 프로젝트 구성은 아래와 같다.
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>
<!-- Test -->
<junit.version>4.11</junit.version>
</properties>
<dependencies>
<!-- Spring and Transactions -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<!-- Logging with SLF4J & LogBack -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
<scope>runtime</scope>
</dependency>
<!-- Test Artifacts -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.5.4</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>3.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.1.0.7.0</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>oracle</id>
<name>ORACLE JDBC Repository</name>
<url>http://maven.jahia.org/maven2</url>
</repository>
</repositories>
</project>
[Emp.java]
package onj.edu.tr1.model;
public class Emp {
int empno;
String ename;
int deptno;
public Emp(int empno, String ename, int deptno) {
this.empno = empno;
this.ename = ename;
this.deptno = deptno;
}
public int getEmpno() { return empno; }
public void setEmpno(int empno) { this.empno = empno; }
public String getEname() { return ename; }
public void setEname(String ename) { this.ename = ename; }
public int getDeptno() { return deptno; }
public void setDeptno(int deptno) { this.deptno = deptno; }
}
[OnjDao.java]
package onj.edu.tr1.dao;
//JdbcDaoSupport클래스는 간단한 DataSource를 지원하기 위해 JdbcTemplate 클래스를 지원.
//jdbcTemplate은 DB연결, PrepatedStatement객체생성, 파라미터주입, SQL문장실행,
//DB접속종료등을 전담하며 getJdbcTemplate()을 통해 얻는다.
@Repository("onjDao")
public class OnjDao{
private JdbcTemplate jdbcTemplate;
@Autowired public void setDataSource(DataSource dataSource){
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public List<Emp> getEmpByDeptno(int deptno) {
String sql = "select empno, ename, deptno from emp where deptno = ?";
List<Emp> list = jdbcTemplate.query(
sql,
new Object[] { deptno },
new RowMapper() {
public Object mapRow(ResultSet rs, int index) throws
SQLException {
int empno = rs.getInt("empno");
String ename = rs.getString("ename");
int deptno = rs.getInt("deptno");
return new Emp(empno, ename, deptno);
}
}
);
return list;
}
public void insertEmps() throws Exception {
String sql = "insert into emp(empno, ename, deptno) values (?, ?, ?)";
jdbcTemplate.update(sql, new Object[] { 111, "Onj1" , 10});
jdbcTemplate.update(sql, new Object[] { 222, "Onj2", 10 });
jdbcTemplate.update(sql, new Object[] { 333, "Onj3", 10 });
//같은 데이터를 넣으면 키값이 중복되어 DataAccessException 발생(런타임예외)
jdbcTemplate.update(sql, new Object[] { 333, "Onj3", 10 });
//throw new Exception();
}
}
[OnjService.java]
package onj.edu.tr1.service;
@Service("onjService")
public class OnjService {
@Autowired
private OnjDao dao;
public OnjService() {}
public OnjService(OnjDao onjDao) {
this.dao = onjDao;
}
public List<Emp> getEmpByDeptno(int deptno) {
return dao.getEmpByDeptno(deptno);
}
public void insertEmps() throws Exception{
dao.insertEmps();
}
}
[onjoraclejava.xml]
<?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:p="http://www.springframework.org/schema/p"
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
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">
<!-- 접속할 DB의 DataSource정의 -->
<bean name="dataSource”
class="org.apache.commons.dbcp.BasicDataSource"
p:driverClassName ="oracle.jdbc.driver.OracleDriver”
p:url = "jdbc:oracle:thin:@192.168.0.27:1521:onj"
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);
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된다.

#20.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/마이바티스학원추천

  • 1.
    스프링프레임워크 & 마이바티스 (SpringFramework, 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>  SpringAOP가 포인트컷 정의를 위해 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>
  • 5.
    <!-- Test --> <junit.version>4.11</junit.version> </properties> <dependencies> <!--Spring and Transactions --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring-framework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring-framework.version}</version> </dependency> <!-- Logging with SLF4J & LogBack --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> <scope>compile</scope> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>${logback.version}</version> <scope>runtime</scope> </dependency> <!-- Test Artifacts --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.5.4</version> </dependency> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>3.2.3.RELEASE</version> </dependency> <dependency> <groupId>com.oracle</groupId>
  • 6.
    <artifactId>ojdbc6</artifactId> <version>11.1.0.7.0</version> </dependency> </dependencies> <repositories> <repository> <id>oracle</id> <name>ORACLE JDBC Repository</name> <url>http://maven.jahia.org/maven2</url> </repository> </repositories> </project> [Emp.java] packageonj.edu.tr1.model; public class Emp { int empno; String ename; int deptno; public Emp(int empno, String ename, int deptno) { this.empno = empno; this.ename = ename; this.deptno = deptno; } public int getEmpno() { return empno; } public void setEmpno(int empno) { this.empno = empno; } public String getEname() { return ename; } public void setEname(String ename) { this.ename = ename; } public int getDeptno() { return deptno; } public void setDeptno(int deptno) { this.deptno = deptno; } } [OnjDao.java] package onj.edu.tr1.dao; //JdbcDaoSupport클래스는 간단한 DataSource를 지원하기 위해 JdbcTemplate 클래스를 지원. //jdbcTemplate은 DB연결, PrepatedStatement객체생성, 파라미터주입, SQL문장실행, //DB접속종료등을 전담하며 getJdbcTemplate()을 통해 얻는다. @Repository("onjDao") public class OnjDao{
  • 7.
    private JdbcTemplate jdbcTemplate; @Autowiredpublic void setDataSource(DataSource dataSource){ this.jdbcTemplate = new JdbcTemplate(dataSource); } public List<Emp> getEmpByDeptno(int deptno) { String sql = "select empno, ename, deptno from emp where deptno = ?"; List<Emp> list = jdbcTemplate.query( sql, new Object[] { deptno }, new RowMapper() { public Object mapRow(ResultSet rs, int index) throws SQLException { int empno = rs.getInt("empno"); String ename = rs.getString("ename"); int deptno = rs.getInt("deptno"); return new Emp(empno, ename, deptno); } } ); return list; } public void insertEmps() throws Exception { String sql = "insert into emp(empno, ename, deptno) values (?, ?, ?)"; jdbcTemplate.update(sql, new Object[] { 111, "Onj1" , 10}); jdbcTemplate.update(sql, new Object[] { 222, "Onj2", 10 }); jdbcTemplate.update(sql, new Object[] { 333, "Onj3", 10 }); //같은 데이터를 넣으면 키값이 중복되어 DataAccessException 발생(런타임예외) jdbcTemplate.update(sql, new Object[] { 333, "Onj3", 10 }); //throw new Exception(); } }
  • 8.
    [OnjService.java] package onj.edu.tr1.service; @Service("onjService") public classOnjService { @Autowired private OnjDao dao; public OnjService() {} public OnjService(OnjDao onjDao) { this.dao = onjDao; } public List<Emp> getEmpByDeptno(int deptno) { return dao.getEmpByDeptno(deptno); } public void insertEmps() throws Exception{ dao.insertEmps(); } } [onjoraclejava.xml] <?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:p="http://www.springframework.org/schema/p" 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 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd"> <!-- 접속할 DB의 DataSource정의 --> <bean name="dataSource” class="org.apache.commons.dbcp.BasicDataSource" p:driverClassName ="oracle.jdbc.driver.OracleDriver” p:url = "jdbc:oracle:thin:@192.168.0.27:1521:onj"
  • 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); } publicstatic 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된다.