구리

TIL_210621_스프링 트랜잭션 처리 본문

SPRING FRAMEWORK

TIL_210621_스프링 트랜잭션 처리

guriguriguri 2021. 6. 21. 21:54

트랜잭션

트랜잭션은 어떤 일련의 작업을 의미 합니다.
어떤 일련의 작업들은 모두 에러 없이 끝나야 하며, 
만약 중간에 에러가 발생 한다면, 에러 발생 이전 시점까지 작업되었던 내용은 모두 원상복구 되어야 합니다.
이렇게 데이터에 대한 무결성을 유지하기 위한 처리 방법을 '트랜잭션 처리' 라고 합니다.

 

 

스프링 트랜잭션 처리 과정 (AOP로 처리)

1. 스프링 설정 XML 파일에서 tx 네임스페이스 추가

 - 반드시 XML 기반으로 설정 (어노테이션 설정 불가능)

 - <aop:advisor> 이용하여 설정 (<aop:aspect> 사용 불가)

 

2. 트랜잭션 관리자 등록

어떤 기술을 이용하느냐에 따라 트랜잭션 관리자도 달라지는데 지금은 DataSource를 이용하기에 DataSourceTransactionManager 클래스 이용할 예정

 

등록 방법

<bean id="객체명" class="트랜잭션 관리자 클래스 경로명">
		<property name="dataSource" ref="미리 등록한 DataSource 객체 id명"></property>
</bean>

DB 접속이 필요하기에 <property> 태그를 이용하여 어떤 접속방식을 이용하는지 전달합니다.

 

예시

<!-- DataSource Configuration properties 파일 이용  -->
	<context:property-placeholder location="classpath:config/database.properties"/>
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
		<property name="driverClassName" value="${jdbc.driver}" />
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
 </bean>
 
 <!-- Transaction Registration -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource"></property>
</bean>

 

 

3. 트랜잭션 처리를 위한 환경설정

<!-- Transaction Configuration -->
	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
			<tx:method name="get*" read-only="true"/>
			<tx:method name="*"/>
		</tx:attributes>
	</tx:advice>
	
<!-- Transaction Advisor Configuration -->
	<aop:config>
		<aop:pointcut expression="execution(* com.springbook.biz..*(..))" id="txPointcut"/>
		<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
	</aop:config>

 - 트랜잭션 관리자를 이용하여 트랜잭션을 제어하는 어드바이스 등록

(스프링 트랜잭션 관련 Advice 클래스는 개발자가 정의하는 것이 아닌 스프링 컨테이너에 의해 <tx:advice>에 설정된 내용을 토대로 설정되기에 개발자는 클래스, 메서드의 종류를 알 수 없습니다. 따라서 어드바이스 객체가 사용할 트랜잭션 관리자를 transaction-manager 속성으로 지정할 뿐입니다.)

- <tx:attributes> 엘리먼트로 트랜잭션을 적용할 메서드 지정

<tx:attributes> 속성 의미
name 트랜잭션이 적용될 메소드 이름 지정
read-only 읽기 전용 여부 지정(기본값 false)
no-rollback-for 트랜잭션을 롤백하지 않을 예외 지정
rollback-for 트랜잭션을 롤백할 예외 지정

 

<tx:attributes>  해석

<tx:method name="get*" read-only="true"/> 

-  get으로 시작하는 모든 메서드는 실제로 데이터를 수정/삭제/추가 하는 메서드가 아닌 단순 조회메서드 이므로  read-only="true"  (읽기 전용) 을 설정함으로써 트랜잭션에서 제외 시킬 수 있습니다.

<tx:method name="*"/>

- 모든 메서드를 트랜잭션 관리 대상으로 설정합니다.

 

따라서 위 설정은 get으로 시작하는 메서드 외의 모든 메서드를 트랜잭션 관리대상으로 지정한다는 의미힙니다.

 

코드 결과

<?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:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	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-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/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">

	<context:component-scan base-package="com.springbook.biz"></context:component-scan>
	
	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
	
	
	<!-- DataSource Configuration properties 파일 이용  -->
	<context:property-placeholder location="classpath:config/database.properties"/>
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
		<property name="driverClassName" value="${jdbc.driver}" />
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
	</bean>
	
	<!-- Spring JDBC Configuration -->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	
	<!-- Transaction Registration -->
	<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!-- Transaction Configuration -->
	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
			<tx:method name="get*" read-only="true"/>
			<tx:method name="*"/>
		</tx:attributes>
	</tx:advice>
	
	<!-- Transaction Advisor Configuration -->
	<aop:config>
		<aop:pointcut expression="execution(* com.springbook.biz..*(..))" id="txPointcut"/>
		<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
	</aop:config>

</beans>