티스토리 뷰

하루종일 고생한 것을 적어봅니다..

 

저의 경우 Spring5 + Mybatis + postgreSql 조합입니다

 

 

dataSource-context.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:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
		http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.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">
	
	<!-- properties -->
	<bean id="propertryConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>classpath:properties/globals.properties</value>
			</list>
		</property>
	</bean>
	
	<!-- mybatis를 활용한 sqlSessionFatory 설정 -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property ref="dataSource" name="dataSource" />
		<property name="configLocation" value="classpath:SqlConfigration.xml" />
		<property name="mapperLocations" value="classpath:sqlmap/*.xml"/>
	</bean>
	
	<!-- sqlSessionTemplate 지정 -->
	<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
		<constructor-arg ref="sqlSessionFactory" />
	</bean>
	
	<!-- DataSource Configuration -->
	<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource">
		<property name="driverClassName" value="${jdbc.driverClassName}" />
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}"/>
		<property name="password" value="${jdbc.password}"/>
		<property name="defaultAutoCommit" value="false"/>
	</bean>
	
	<!-- Transaction 설정 -->	
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
			<property name="dataSource" ref="dataSource"/>
	</bean>
	
	<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
	
	<!-- Transaction 어노테이션없이 설정 -->
<!-- <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="select*" rollback-for="Exception" read-only="true"/>
            <tx:method name="update*" rollback-for="Exception"/>
            <tx:method name="insert*" rollback-for="Exception"/>
            <tx:method name="delete*" rollback-for="Exception"/>
        </tx:attributes>
    </tx:advice>

	<aop:config>
	    <aop:pointcut expression="execution(* com.groupware.service..*ServiceImpl.*(..))" id="serviceMethod"/>
	    <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod" id="transactionAdvisor"/>
	</aop:config> -->

</beans>

 

service

import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.groupware.dao.HomeDaoImpl;

@Service
public class HomeServiceImpl implements HomeService{
	@Autowired
	SqlSessionTemplate sqlSessionTemplate;
	
	@Autowired
	HomeDaoImpl homeDao;
	
	@Transactional(rollbackFor = {Exception.class})
	public void insertText(String str) {
		
	
			//rollback 되어야하는 메소드
			homeDao.insertText(str);
			//오류 발생
			homeDao.insertText2(str);

	}	
	

}

 

Dao

import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@Repository
public class HomeDaoImpl {
	@Autowired
	SqlSessionTemplate sqlSessionTemplate;
	
	public void insertText(String str){

		sqlSessionTemplate.insert("sample.insertText01", str);
	}
	
	public void insertText2(String str){

		sqlSessionTemplate.insert("sample.insertText02", str);
		throw new RuntimeException();//
	}
}

 

 

먼저 service의 insertText를 보면  dao의 insertText와 insertText2 메소드를 불러온다.

 

그 중에 dao의 insertText2에서 일부러 runtimeException을 일으키는데

 

오류가 날 경우 service의 insertText 에 트랜젝션을 걸어 두었기에 dao의 insertText,insertText2 모두 롤백되어야만 한다.

 

하지만 계속 오류가 날지언정 롤백은 되지않았다

 

인터페이스를 만들거나 여러 질문글을 남긴 후에 계속해서 구글링을 해보았더니 해결을 하게 되었다.

 

나의 경우 DataSource-context.xml에 스캐닝을 걸었다

	<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>

바로 이 부분인데

 

글을 찾아보는 중

root-context.xml에서는 servelt-context.xml에서 등록된 bean에 접근할 수 없다.

servlet-context.xml에서는 root-contet.xml에서 등록된 bean에 접근할 수 있다.

라는 부분을 보게 되었다.

 

이건 순서의 문제라고 생각되었다.

 

스캐닝이 되는 시점을 servlet에서 준다면 될지 모른다 생각해

 

servlet-context.xml에 <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>

해당 코드를 넣었다.

 

놀랍게도 잘 돌아갔다..

 

이후 에러 처리 후에도 잘 돌아가게 되었다

 

	
	@Transactional(rollbackFor = {Exception.class})
	public int insertText(String str) {
		
			try {
			//rollback 되어야하는 메소드
			homeDao.insertText(str);
			//오류 발생
			homeDao.insertText2(str);
			}catch(Exception e) {
				return 1;
			}
			
		return 0;
	}
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함