프로젝트에 logback 적용에 이해 Transaction을 적용하도록 하겠습니다.
Transaction의 방식에는 두 가지 방법이 있습니다.
1. @Transaction을 이용해 적용한다.
2. root-context.xml(spring regacy project) 또는 dispatcher-servlet-xml(maven project)에 해당 서비스 Impl을 지정하여 전체 Transaction을 적용한다.
1번과 2번의 차이는 확연합니다.
1번의 방식을 진행하면 필요한 것만 할 수 있다.
2번의 방식을 진행하면 간편하게 묶어 줄 수 있다.(1번의 방식으로 많은 service 메서드들을 하나하나 적용하기 힘들다.)
저희는 2번의 방법을 사용할것입니다.
이제 프로젝트에 적용해보도록 하겠습니다.
<!-- pom.xml -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-tx -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
여기서 알아야 할 것이 있는데
@Transaction을 사용하려면 cglib 라이브러리를 dependency에 추가해야 합니다.
추가해야하는 이유는 차후에 작성하도록 하겠습니다.
<!-- dispatcher-servlet.xml -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" <!-- 추가 -->
xsi:schemaLocation="
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 <!-- 추가 -->
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- net.eduSample로 시작하는 패키지를 모두 등록 -->
<!-- <context:component-scan base-package="net.eduSample" /> -->
<context:component-scan base-package="net.eduSample.*" />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/jsp/</value> <!-- 접두어 -->
</property>
<property name="suffix">
<value>.jsp</value> <!-- 접미어 -->
</property>
</bean>
<!-- <mvc:resources mapping="/resources/**" location="/resources/" /> -->
<mvc:resources mapping="/static/**" location="/static/" />
<mvc:resources mapping="/favicon.ico" location="/WEB-INF/img/common/favicon.ico" />
<mvc:annotation-driven />
<bean id="AdminInterceptor" class="net.eduSample.interceptor.AdminInterceptor" />
<!-- Interceptor 설정 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/admin/**" />
<mvc:mapping path="/user/userAll" />
<mvc:mapping path="/user/userIntegrated" />
<mvc:mapping path="/user/userHistory" />
<!-- <mvc:exclude-mapping path="/resources/**"/> -->
<ref bean="AdminInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
<!-- transaction -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" /> <!-- 트랜잭션 대상 선정. 바뀔 일 없고 이후 복사해서 사용 -->
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" rollback-for="Exception" />
</tx:attributes>
</tx:advice>
<!-- package net.eduSample.sample.service.impl -->
<aop:config>
<aop:pointcut id="txPointcut"
expression="execution(* net.eduSample.sample.service.impl.*ServiceImpl.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" />
</aop:config>
<tx:annotation-driven transaction-manager="transactionManager"
proxy-target-class="true" />
</beans>
다음과 같이 적용 후
serviceImpl 파일로 가서 insert와 update를 진행하는 메서드를 작성 후
insert나 update 중 하나를 mapper에 고의로 오타를 내서 확인해보면
에러가 나도 DB에 값이 들어가지 않고 모두 롤백되는것을 볼 수 있습니다.