Spring Framework 4.3.11 기준으로 Atomikos 4.0.4 설정 방법을 알아보겠다.
Atomikos와 관련있는 Spring 설정만 알아본다.
Atomikos 홈페이지는 아래 링크이다.
https://www.atomikos.com
유료 버전과 무료 버전이 존재하는데 차이점은 하위 버전과 기술지원을 받을 수 있는 차이가 있는 것 같다.
자세한 건 홈페이지에서 확인하기 바란다.
아래 예제의 패키지명 등 각 설정값들은 임의로 넣음
트랜잭션 방식은 @Transactional 어노테이션을 사용
메이븐 pom.xml
<!-- myBatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<!-- MariaDB JDBC -->
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>1.6.5</version>
</dependency>
<!-- Atomikos -->
<dependency>
<groupId>com.atomikos</groupId>
<artifactId>transactions-jta</artifactId>
<version>4.0.4</version>
</dependency>
<dependency>
<groupId>com.atomikos</groupId>
<artifactId>transactions-jdbc</artifactId>
<version>4.0.4</version>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>1.1</version>
</dependency>
Spring xml 설정
컨트롤러를 제외한 component-scan은 web.xml의 contextConfigLocation에 지정한 xml 파일에서 해야 함
그렇지 않으면 트랜잭션이 수행 안됨
<context:component-scan base-package="com.my.app">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
Spring Atomikos 설정
<?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:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd
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.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<!-- Atomikos 설정 start -->
<bean id="userTransactionService" class="com.atomikos.icatch.config.UserTransactionServiceImp" init-method="init" destroy-method="shutdownForce">
<constructor-arg>
<props>
<prop key="com.atomikos.icatch.service">
com.atomikos.icatch.standalone.UserTransactionServiceFactory
</prop>
</props>
</constructor-arg>
</bean>
<!-- Construct Atomikos UserTransactionManager, needed to configure Spring -->
<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close" depends-on="userTransactionService">
<property name="startupTransactionService" value="false" />
<property name="forceShutdown" value="false" />
</bean>
<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp" depends-on="userTransactionService">
<property name="transactionTimeout" value="300" />
</bean>
<!-- JTA 트랜잭션 설정 -->
<bean id="jtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" depends-on="userTransactionService">
<property name="transactionManager" ref="atomikosTransactionManager" />
<property name="userTransaction" ref="atomikosUserTransaction" />
</bean>
<!-- @Transactional 사용 설정 -->
<tx:annotation-driven transaction-manager="jtaTransactionManager" />
<!-- DataSource1 설정 -->
<bean id="testDataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean">
<property name="uniqueResourceName" value="test" />
<property name="xaDataSourceClassName" value="org.mariadb.jdbc.MariaDbDataSource" />
<property name="xaProperties">
<props>
<prop key="url">jdbc:mariadb://localhost:3306/test</prop>
<prop key="user">test</prop>
<prop key="password">test</prop>
</props>
</property>
<property name="poolSize" value="50" />
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="testDataSource" />
<property name="mapperLocations" value="classpath*:mappers/mariadb/test/**/*.xml" />
<property name="configuration">
<bean class="org.apache.ibatis.session.Configuration">
<property name="mapUnderscoreToCamelCase" value="true" />
</bean>
</property>
</bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean>
<mybatis-spring:scan base-package="com.my.app.test.*.mapper" factory-ref="sqlSessionFactory" template-ref="sqlSession" />
<!-- DataSource2 설정 -->
<bean id="testDataSource2" class="com.atomikos.jdbc.AtomikosDataSourceBean">
<property name="uniqueResourceName" value="test2" />
<property name="xaDataSourceClassName" value="org.mariadb.jdbc.MariaDbDataSource" />
<property name="xaProperties">
<props>
<prop key="url">jdbc:mariadb://localhost:3306/test2</prop>
<prop key="user">test2</prop>
<prop key="password">test2</prop>
</props>
</property>
<property name="poolSize" value="50" />
</bean>
<bean id="sqlSessionFactory2" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="testDataSource2" />
<property name="mapperLocations" value="classpath*:mappers/mariadb/test2/**/*.xml" />
<property name="configuration">
<bean class="org.apache.ibatis.session.Configuration">
<property name="mapUnderscoreToCamelCase" value="true" />
</bean>
</property>
</bean>
<bean id="sqlSession2" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory2" />
</bean>
<mybatis-spring:scan base-package="com.my.app.test2.*.mapper" factory-ref="sqlSessionFactory2" template-ref="sqlSession2" />
</beans>
Spring Service 클래스
@Service
public class xxxService {
@Transactional
public int insert() {
...
}
}
그럼 아래와 같이 로그가 찍힘
아래 로그 내용은 서로 다른 DB에서 insert가 수행됐는데
첫 번째 insert는 성공했고 두 번째 insert는 실패하여
첫 번째, 두 번째 트랜잭션이 동시에 롤백되는 로그이다.
[http-nio-8080-exec-3] DEBUG o.s.t.jta.JtaTransactionManager - Creating new transaction with name [com.my.app.test.user.service.UserService.insertUser]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
[http-nio-8080-exec-3] DEBUG c.a.i.i.CompositeTransactionManagerImp - createCompositeTransaction ( 10000 ): created new ROOT transaction with id 192.168.1.105.tm150817196160700002
[http-nio-8080-exec-3] DEBUG c.a.jdbc.AbstractDataSourceBean - AtomikosDataSoureBean 'test': getConnection()...
[http-nio-8080-exec-3] INFO c.a.jdbc.AbstractDataSourceBean - AtomikosDataSoureBean 'test': init...
[http-nio-8080-exec-3] DEBUG c.a.jdbc.AtomikosConnectionProxy - atomikos connection proxy for org.mariadb.jdbc.MariaDbConnection@52529bf6: calling getAutoCommit...
[http-nio-8080-exec-3] DEBUG c.m.a.t.u.m.UserMapper.insertUser - ==> Preparing: insert into user (user_id, user_name) values(?, ?)
[http-nio-8080-exec-3] DEBUG c.a.i.imp.CompositeTransactionImp - addParticipant ( XAResourceTransaction: 3139322E3136382E312E3130352E746D313530383137313936313630373030303032:3139322E3136382E312E3130352E746D33 ) for transaction 192.168.1.105.tm150817196160700002
[http-nio-8080-exec-3] DEBUG c.a.d.xa.XAResourceTransaction - XAResource.start ( 3139322E3136382E312E3130352E746D313530383137313936313630373030303032:3139322E3136382E312E3130352E746D33 , XAResource.TMNOFLAGS ) on resource test represented by XAResource instance org.mariadb.jdbc.MariaXaResource@5dc43247
[http-nio-8080-exec-3] DEBUG c.a.i.imp.CompositeTransactionImp - registerSynchronization ( com.atomikos.jdbc.AtomikosConnectionProxy$JdbcRequeueSynchronization@48499297 ) for transaction 192.168.1.105.tm150817196160700002
[http-nio-8080-exec-3] DEBUG c.a.jdbc.AtomikosConnectionProxy - atomikos connection proxy for org.mariadb.jdbc.MariaDbConnection@52529bf6: calling prepareStatement(insert into user (user_id, user_name) values(?, ?))...
[http-nio-8080-exec-3] DEBUG c.m.a.t.u.m.UserMapper.insertUser - ==> Parameters: test1(String), 테스트1(String)
[http-nio-8080-exec-3] DEBUG c.m.a.t.u.m.UserMapper.insertUser - <== Updates: 1
[http-nio-8080-exec-3] DEBUG c.a.jdbc.AbstractDataSourceBean - AtomikosDataSoureBean 'test2': getConnection()...
[http-nio-8080-exec-3] INFO c.a.jdbc.AbstractDataSourceBean - AtomikosDataSoureBean 'test2': init...
[http-nio-8080-exec-3] DEBUG c.a.jdbc.AtomikosConnectionProxy - atomikos connection proxy for org.mariadb.jdbc.MariaDbConnection@57da83a7: calling getAutoCommit...
[http-nio-8080-exec-3] DEBUG c.m.a.t.u.m.User2Mapper.insertUser - ==> Preparing: insert into user (user_id, user_name) values(?, ?)
[http-nio-8080-exec-3] DEBUG c.a.i.imp.CompositeTransactionImp - addParticipant ( XAResourceTransaction: 3139322E3136382E312E3130352E746D313530383137313936313630373030303032:3139322E3136382E312E3130352E746D34 ) for transaction 192.168.1.105.tm150817196160700002
[http-nio-8080-exec-3] DEBUG c.a.d.xa.XAResourceTransaction - XAResource.start ( 3139322E3136382E312E3130352E746D313530383137313936313630373030303032:3139322E3136382E312E3130352E746D34 , XAResource.TMNOFLAGS ) on resource test2 represented by XAResource instance org.mariadb.jdbc.MariaXaResource@7d6a9358
[http-nio-8080-exec-3] DEBUG c.a.i.imp.CompositeTransactionImp - registerSynchronization ( com.atomikos.jdbc.AtomikosConnectionProxy$JdbcRequeueSynchronization@48499297 ) for transaction 192.168.1.105.tm150817196160700002
[http-nio-8080-exec-3] DEBUG c.a.jdbc.AtomikosConnectionProxy - atomikos connection proxy for org.mariadb.jdbc.MariaDbConnection@57da83a7: calling prepareStatement(insert into user (user_id, user_name) values(?, ?))...
[http-nio-8080-exec-3] DEBUG c.m.a.t.u.m.User2Mapper.insertUser - ==> Parameters: test2(String), 테스트2(String)
[http-nio-8080-exec-3] DEBUG c.a.jdbc.AtomikosConnectionProxy - atomikos connection proxy for org.mariadb.jdbc.MariaDbConnection@52529bf6: close()...
[http-nio-8080-exec-3] DEBUG c.a.d.xa.XAResourceTransaction - XAResource.end ( 3139322E3136382E312E3130352E746D313530383137313936313630373030303032:3139322E3136382E312E3130352E746D33 , XAResource.TMSUCCESS ) on resource test represented by XAResource instance org.mariadb.jdbc.MariaXaResource@5dc43247
[http-nio-8080-exec-3] DEBUG c.a.jdbc.AtomikosConnectionProxy - atomikos connection proxy for org.mariadb.jdbc.MariaDbConnection@57da83a7: close()...
[http-nio-8080-exec-3] DEBUG c.a.d.xa.XAResourceTransaction - XAResource.end ( 3139322E3136382E312E3130352E746D313530383137313936313630373030303032:3139322E3136382E312E3130352E746D34 , XAResource.TMSUCCESS ) on resource test2 represented by XAResource instance org.mariadb.jdbc.MariaXaResource@7d6a9358
[http-nio-8080-exec-3] DEBUG o.s.t.jta.JtaTransactionManager - Initiating transaction rollback
[http-nio-8080-exec-3] DEBUG c.a.d.xa.XAResourceTransaction - XAResource.rollback ( 3139322E3136382E312E3130352E746D313530383137313936313630373030303032:3139322E3136382E312E3130352E746D33 ) on resource test represented by XAResource instance org.mariadb.jdbc.MariaXaResource@5dc43247
[http-nio-8080-exec-3] DEBUG c.a.d.xa.XAResourceTransaction - XAResource.rollback ( 3139322E3136382E312E3130352E746D313530383137313936313630373030303032:3139322E3136382E312E3130352E746D34 ) on resource test2 represented by XAResource instance org.mariadb.jdbc.MariaXaResource@7d6a9358
[http-nio-8080-exec-3] DEBUG c.a.i.imp.CompositeTransactionImp - rollback() done of transaction 192.168.1.105.tm150817196160700002
[http-nio-8080-exec-3] DEBUG c.a.i.imp.CompositeTransactionImp - rollback() done of transaction 192.168.1.105.tm150817196160700002
끝.
'Spring' 카테고리의 다른 글
Spring 4.3 Redis Sentinel Pubsub 설정 (0) | 2018.06.16 |
---|---|
Spring 4.3 Redis Sentinel 연동 (0) | 2018.06.16 |
Spring 4 JSR-303 Validator (0) | 2017.06.12 |
Spring REST Docs 사용법 (0) | 2017.04.23 |
Spring ehcache 설정 (0) | 2016.12.12 |
댓글