지난 포스팅에 이어서 service 영역에 트랜잭션 처리를 하고자 한다.
2014/07/23 - [스프링연동하기/spring3 mybatis 설정] - 스프링(Spring)3 - mybatis 연동(1)
@transactional인가 어노테이션으로 트랜잭션을 주는 방식도 있긴하지만, xml 설정을 함으로
service영역에서의 트랜잭션 처리를 하고자한다.
현재 방식으로 insert 쿼리 여러개를 선언하고 중간에 오류를 발생시키면 오류나기 전에 있던
데이터들은 insert가 되어진다.
이부분을 막고자 트랜잭션설정을 주려고 한다.
뭐 트랜잭션 신경 안쓰시려고는 분들은 이번 포스팅을 넘기셔도 무관함..
트랜잭션 처리를위한 추가 dependency를 pom.xml에 등록해주도록 하자
<dependency> <groupId>aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.5.3</version> </dependency> <dependency> <groupId>cglib</groupId> <artifactId>cglib-nodep</artifactId> <version>2.1_3</version> </dependency>
기존 mvc-config.xml에 정의해주었던 component-scan을 다음과 같이 변경해주도록 하자
수정전
<context:component-scan base-package="com.spring.web"/>
수정 후
<context:component-scan base-package="com.spring.web" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /> </context:component-scan>
이어서 application-config.xml에 내용 추가 및 수정을 해주도록 하자
<bean> 태그가 아닌 전체 xml을 감싸고 있는 <beans>태그가 있을 텐데 다음과 같이
변경 해주도록 하자
<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:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
aop 부분과 tx 부분만 추가 되었다.
이제 트랜잭션 설정을 해주도록 하자
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <aop:config proxy-target-class="true"> <aop:pointcut id="serviceOperation" expression="execution(public * com.spring.web..service.*Service.*(..))" /> <aop:advisor id="transactionAdvisor" pointcut-ref="serviceOperation" advice-ref="txAdvice"/> </aop:config> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="save*" rollback-for="Exception"/> <tx:method name="update*" rollback-for="Exception"/> <tx:method name="remove*" rollback-for="Exception"/> </tx:attributes> </tx:advice>
위와같이 해주었다면 트랜잭션 설정이 모두 마무리가 되었다.
임의의 테이블을 만들고 트랜잭션 테스트를 해보도록 하자
※ mysql 경우 table type이 innodb여야 트랜잭션처리가 적용이된다.
create table 샘플코드
CREATE TABLE `test` ( `test_column` varchar(5) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8
테이블 생성이 완료 되었다면 이제는 클래스에 controller/service/dao를 추가해주도록 하자
지난 포스팅에는 그냥 web내부에 controller/dao 패키지를 생성하였는데
web 패키지에 추가로 새로운 패키지를 생성하여 내부에 controller/service/dao를 작성하도록 하겠음.
패키지 구성은 다음과 같음.
다음구조와 같이 만들었다면 controller/service/dao 부분에 대하여 샘플 코드를 작성하도록 하자
TestController.java 코드
@Controller public class TestController { @Autowired private TestService service; @RequestMapping(value="/saveQuery") public void saveQuery(){ try { service.saveQuery(); } catch (SQLException e) { e.printStackTrace(); } } }
TestService.java 코드
@Service public class TestService { @Autowired private TestDao dao; public void saveQuery() throws SQLException { Map<String, String> map = null; map = new HashMap<String, String>(); map.put("test", "123"); dao.saveQuery(map); map = new HashMap<String, String>(); map.put("test", "1231111111111111"); dao.saveQuery(map); map = new HashMap<String, String>(); map.put("test", "123"); dao.saveQuery(map); } }
TestDao.java코드
@Repository public class TestDao { @Autowired private SqlSession sql; public void saveQuery(Map<String, String> map) throws SQLException { sql.insert("sql.saveQuery",map); } }
마지막으로 sql.xml에 insert 쿼리 하나를 작성해주도록 하자
<insert id="saveQuery" parameterType="java.util.Map"> INSERT INTO test VALUES(#{test}) </insert>
위의 로직상 설명을 한다면 return 타입은 없어서 우선적으로 웹페이지는 뜨지 않을것이다.
그리고 service 부분에 총 3번의 dao를 호출하는데 test 테이블의 test_column 컬럼의 제한수가
총 5글자가 들어갈수 있다.
즉, 첫번째 insert는 정상적으로 테이블에 등록되고 두번째 insert에는 exception이 발생하여
에러를 웹이랑 콘솔에 뿜을것이다.
그리고는 테이블에 데이터가 등록되지 않은것을 확인 하였다면 정상적으로 트랜잭션 처리가 된것임.
※ 주의할점
application-config.xml 에 tx:advice태그내에 tx:method 가 몇가지 있는데
tx:method의 name을 보면 save* << 이런식으로 주었다.
service의 메서드 시작문구가 save로 시작된다면 트랜잭션 적용을 한다는 의미이다.
만약 본인이 abcTest() << 라는 메서드로 트랜잭션 처리를 하고 싶다면
다음과 같이 태그 추가를 해주면 될것이다.
<tx:method name="abc*" rollback-for="Exception"/>
그리고 service / dao 클래스에 try/catch를 주지말고 throws SQLException 형식으로 처리를
해준다음 controller에서 try{}catch{}로 잡아주어야 할것이다.
★ 추가된 내용 ★
간혹가다가 트랜잭션 처리가 안될경우 mvc-config.xml 에 다음처럼 aop 추가를 해주도록 하자
<aop:config proxy-target-class="true"> <aop:pointcut id="controllerOperation" expression="execution(public * com.spring.web..controller.*Controller.*(..))" /> </aop:config>
도움이 되셨다면 공감클릭! 궁금하신점은 댓글!!
스프링3(Spring3) - ibatis 연동하기 (0) | 2014.08.20 |
---|---|
스프링3(Spring3) - mybatis 연동(3) 다중DB 접속 + 트랜잭션 설정 (6) | 2014.07.28 |
스프링3(Spring3) - mybatis 연동(1) (6) | 2014.07.23 |