탑크리에듀교육센터(www.topcredu.co.kr)제공
스프링프레임워크 & 마이바티스(Spring Framework, MyBatis)
21번째 자료입니다. 참고하시어 많은 도움되셨길 바랍니다.
교육 및 수강문의/기타문의사항은 홈페이지(www.topcredu.co.kr)를 통하여 하실 수 있습니다.^^
1. 스프링프레임워크 & 마이바티스
(Spring Framework, MyBatis)
5-4-2. 스프링 선언적 트랜잭션 관리 – @Transactional 개요
XML 설정에 <tx:annotation-driven /> 요소가 설정 되어 있다면 트랜잭션을 어노테이션으로
설정 가능 하다. 이 방법은 직관적이고 알기 쉽지만 수정시 자바 코드 자체를 수정해야 한다
는 단점이 있다.
트랜잭션 처리를 원하는 메서드에 @Transactional이란 어노테이션을 사용하면 되고 <aop>설
정은 어노테이션과 젂혀 무관하다.
인터페이스, 클래스, 메서드에 동시에 트랜잭션 어노테이션이 설정 되어 있다면 스프링은 메
서드 어노테이션을 제일 먼저 고려하고 그 다음이 클래스, 인터페이스 순서로 고려 합니다.
5-4-2-1. 스프링 선언적 트랜잭션 관리 – @Transactional 예제
springtr2라는 이름으로 spring maven Project를 생성하자.(EMP 테이블 데이터를 SELECT하고
INSERT하는 예제)
2. 젂체 프로젝트 구성은 아래와 같다.
STS에서
New Project Spring Legacy Project
Project Name : springtr2
Simple Projects : Simple Spring Maven
[OnjDao.java]
package onj.edu.tr1.dao;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import javax.sql.DataSource;
import onj.edu.tr1.model.Emp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
3. import org.springframework.transaction.annotation.Transactional;
//JdbcDaoSupport클래스는 간단한 DataSource를 지원하기 위해 JdbcTemplate 클래스를 지원.
//jdbcTemplate은 DB연결, PrepatedStatement객체생성, 파라미터주입, SQL문장실행,
//DB접속종료등을 전담하며 getJdbcTemplate()을 통해 얻는다.
@Repository("onjDao")
public class OnjDao{
private JdbcTemplate jdbaTemplate;
@Autowired
public void setDataSource(DataSource dataSource){
this.jdbaTemplate = new JdbcTemplate(dataSource);
}
public List<Emp> getEmpByDeptno(int deptno) {
String sql = "select empno, ename, deptno from emp where deptno = ?";
List<Emp> list = jdbaTemplate.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;
}
@Transactional
public void insertEmps() throws Exception {
String sql = "insert into emp(empno, ename, deptno) values (?, ?, ?)";
jdbaTemplate.update(sql, new Object[] { 1771, "오자바1" , 10});
5. class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<context:component-scan base-package="onj.edu.tr1.dao" />
<context:component-scan base-package="onj.edu.tr1.service" />
</beans>
5-4-2-2. @Transactional 메소드 내부에서 다른 메소드 호출의 경우
트랜잭션 적용범위
@Transactional 어노테이션은 Proxy기반이므로 내부 메소드 호출인 경우 트랜잭션이 적용되
지 않는다. 즉 현재 클래스의 메소드가 아닌 다른 클래스의 메소드에 트랜잭션을 걸어야 한다.
@Service
class MyService {
@Autowired
A a;
@Transactional
public void myService() {
a.trTest();
}
}
@Service
class A {
@Transactional
trTest() {
tr1();
tr2();
}
@Transactional
6. void tr1() { ... }
@Transactional
void tr2() { ... }
}
이러한 경우 MyService 직접 tr1(), tr2()를 호출하던지, 아니면 별도의 클래스를 만들어서 tr1(),
tr2()를 구현하면 된다.
- 서비스에서 tr1(), tr2() 각각 호출
@Service
class MyService {
@Autowired
A a;
@Transactional
public void myService() {
a.tr1();
a.tr2();
}
}
@Service
class A {
@Transactional
void tr1() { ... }
@Transactional
void tr2() { ... }
}
- 별도 클래스 만든 후 그 클래스의 tr1(), tr2() 호출하는 경우
@Service
class MyService {
@Autowired
A a;
@Transactional
7. public void myService() {
a.trTest();
}
}
@Service
class A {
@Autowired
B b;
@Transactional
trTest() {
b.tr1();
b.tr2();
}
}
@Service
class B {
@Transactional
void tr1() { ... }
@Transactional
void tr2() { ... }
}