Distributed transaction atomikos

       The last article introduced the sub-database sub-table plug-in, but multi-database operations involve distributed transactions. We all know that distributed transactions need to involve database XA drivers. Oracle originally supports this attribute. MySQL supports this attribute in version 5.6. atomikos The plugin encapsulates a middleware for this feature. Now to introduce the use of an atomikos.

       The first is the jar package dependency. The maven configuration is as follows:

<dependency>
	<groupId>com.atomikos</groupId>
	<artifactId>transactions</artifactId>
	<version>4.0.4</version>
</dependency>
<dependency>
	<groupId>com.atomikos</groupId>
	<artifactId>transactions-api</artifactId>
	<version>4.0.4</version>
</dependency>
<dependency>
	<groupId>com.atomikos</groupId>
	<artifactId> atomikos-util </artifactId>
	<version>4.0.4</version>
</dependency>
<dependency>
	<groupId>com.atomikos</groupId>
	<artifactId>transactions-jdbc-deprecated</artifactId>
	<version>3.8.0</version>
</dependency>
<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>

      In addition, the configuration of jta should be added, and the spring transaction should be managed by jta:

<dependency>
	<groupId>javax.transaction</groupId>
	<artifactId>jta</artifactId>
	<version>1.1</version>
</dependency>

 Then there is the srping configuration. Since the atomikos data source needs to be used, the data source configuration of the previous sub-database sub-table plugin has been modified:

<?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:rdb="http://www.dangdang.com/schema/ddframe/rdb"
	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-4.0.xsd
			http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
			http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
			http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
	        http://www.dangdang.com/schema/ddframe/rdb
		    http://www.dangdang.com/schema/ddframe/rdb/rdb.xsd"
            >

	<!-- configure data source -->
	<bean name="dataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" destroy-method="close">
		<!--		<property name="driverClassName" value="${jdbc.driverClassName}" /> -->
		<property name="uniqueResourceName" value="dataSource" />
		<property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />
		<property name="xaProperties">
			<props>
				<prop key="user">${jdbc.username}</prop>
				<prop key="password">${jdbc.password}</prop>
				<prop key="url">${jdbc.url}</prop>
			</props>
		</property>
		<property name="minPoolSize" value="5" />
		<property name="maxPoolSize" value="50" />
		<property name="maxIdleTime" value="60" />
	</bean>

	<!-- configure data source -->
	<bean name="master0" class="com.atomikos.jdbc.AtomikosDataSourceBean"  destroy-method="close">
		<!--		<property name="driverClassName" value="${jdbc.driverClassName}" /> -->
		<property name="uniqueResourceName" value="master0" />
		<property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />
		<property name="xaProperties">
			<props>
				<prop key="user">${jdbc.username}</prop>
				<prop key="password">${jdbc.password}</prop>
				<prop key="url">jdbc:mysql://127.0.0.1:3306/demodb00</prop>
			</props>
		</property>
		<property name="minPoolSize" value="5" />
		<property name="maxPoolSize" value="50" />
		<property name="maxIdleTime" value="60" />
	</bean>

	<!-- configure data source -->
	<bean name="master1" class="com.atomikos.jdbc.AtomikosDataSourceBean"  destroy-method="close">
		<!--		<property name="driverClassName" value="${jdbc.driverClassName}" /> -->
		<property name="uniqueResourceName" value="master1" />
		<property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />
		<property name="xaProperties">
			<props>
				<prop key="user">${jdbc.username}</prop>
				<prop key="password">${jdbc.password}</prop>
				<prop key="url">jdbc:mysql://127.0.0.1:3306/demodb01</prop>
			</props>
		</property>
		<property name="minPoolSize" value="5" />
		<property name="maxPoolSize" value="50" />
		<property name="maxIdleTime" value="60" />
	</bean>

	<rdb:strategy id="idDbSharding" sharding-columns="id"
				  algorithm-class="com.feng.splitdbtb.DbAlgorithm"/>

	<rdb:strategy id="idTbSharding" sharding-columns="id"
				  algorithm-class="com.feng.splitdbtb.TbAlgorithm"/>

	<rdb:data-source id="wholeDataSource">
		<rdb:sharding-rule data-sources="master0,master1">
			<rdb:table-rules>
				<rdb:table-rule logic-table="user" actual-tables="user_${0..1}"
								database-strategy="idDbSharding" table-strategy="idTbSharding"/>
			</rdb:table-rules>
		</rdb:sharding-rule>
	</rdb:data-source>

	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="wholeDataSource" />
		<property name="configLocation" value="classpath:mybatis-config.xml"/>
		<property name="mapperLocations"  >
			<list>
				<value>classpath:com/feng/mapper/user/*.xml</value>
			</list>
		</property>
	</bean>

	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="com.feng.dao.user" />
		<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
	</bean>

	<!-- define transaction-->
	<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
		  init-method="init" destroy-method="close">
		<property name="forceShutdown">
			<value>true</value>
		</property>
	</bean>

	<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
		<property name="transactionTimeout" value="300" />
	</bean>

	<bean id="springTransactionManager"
		  class="org.springframework.transaction.jta.JtaTransactionManager">
		<property name="transactionManager">
			<ref bean="atomikosTransactionManager" />
		</property>
		<property name="userTransaction">
			<ref bean="atomikosUserTransaction" />
		</property>
		<property name="allowCustomIsolationLevels" value="true"/>
	</bean>
	<tx:advice id="txAdvice" transaction-manager="springTransactionManager">
		<tx:attributes>
			<tx:method name="publish*" />
			<tx:method name="save*" />
			<tx:method name="add*" />
			<tx:method name="update*" />
			<tx:method name="insert*" />
			<tx:method name="create*" />
			<tx:method name="del*" />
			<tx:method name="load*" />
			<tx:method name="init*" />

			<tx:method name="*"  read-only="true"/>
		</tx:attributes>
	</tx:advice>
 	<!-- AOP configuration-->
	<aop:config>
		<aop:pointcut id="myPointcut"
			expression="execution(public * com.feng.service.impl.*.*(..))" />
		<aop:advisor advice-ref="txAdvice" pointcut-ref="myPointcut" />
	</aop:config>

	<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
		<constructor-arg index="0" ref="sqlSessionFactory" />
	</bean>
</beans>

       Run it and see the following log, the brothers have succeeded. There is a frenzy in the heart, and the chest is straight.    

[DEBUG][2017-04-17 09:58:27,821][com.atomikos.icatch.imp.CompositeTransactionImp]addParticipant ( XAResourceTransaction: 636F6D2E61746F6D696B6F732E737072696E672E6A6462632E746D313439323339343330373730353030303035:636F6D2E61746F6D696B6F732E737072696E672E6A6462632E746D35 ) for transaction com.atomikos.spring.jdbc.tm149239430770500005
[DEBUG][2017-04-17 09:58:27,821][com.atomikos.datasource.xa.XAResourceTransaction]XAResource.start ( 636F6D2E61746F6D696B6F732E737072696E672E6A6462632E746D313439323339343330373730353030303035:636F6D2E61746F6D696B6F732E737072696E672E6A6462632E746D35 , XAResource.TMNOFLAGS ) on resource master1 represented by XAResource instance com.mysql.jdbc.jdbc2.optional.JDBC4MysqlXAConnection@2c7e446d
[DEBUG][2017-04-17 09:58:27,840][com.atomikos.icatch.imp.CompositeTransactionImp]registerSynchronization ( com.atomikos.jdbc.AtomikosConnectionProxy$JdbcRequeueSynchronization@1f21ef16 ) for transaction com.atomikos.spring.jdbc.tm149239430770500005
[DEBUG][2017-04-17 09:58:27,841][com.atomikos.jdbc.AtomikosConnectionProxy]atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@2015fa5c: calling prepareStatement(INSERT INTO user_1 (id, name, age) VALUES (?, ?, ?),1003,1007,1)...
[DEBUG][2017-04-17 09:58:27,866][org.mybatis.spring.SqlSessionUtils]Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@ac88402]
[DEBUG][2017-04-17 09:58:27,866][org.mybatis.spring.SqlSessionUtils]Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@ac88402]
[DEBUG][2017-04-17 09:58:27,866][org.mybatis.spring.SqlSessionUtils]Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@ac88402]
[DEBUG][2017-04-17 09:58:27,866][org.springframework.jdbc.datasource.DataSourceUtils]Returning JDBC Connection to DataSource
[DEBUG] [2017-04-17 09: 58: 27,866] [com.atomikos.jdbc.AtomikosConnectionProxy] atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@2015fa5c: close () ...
[DEBUG][2017-04-17 09:58:27,866][com.atomikos.datasource.xa.XAResourceTransaction]XAResource.end ( 636F6D2E61746F6D696B6F732E737072696E672E6A6462632E746D313439323339343330373730353030303035:636F6D2E61746F6D696B6F732E737072696E672E6A6462632E746D35 , XAResource.TMSUCCESS ) on resource master1 represented by XAResource instance com.mysql.jdbc.jdbc2.optional.JDBC4MysqlXAConnection@2c7e446d
[DEBUG][2017-04-17 09:58:27,885][org.springframework.transaction.jta.JtaTransactionManager]Initiating transaction rollback
[DEBUG][2017-04-17 09:58:27,887][com.atomikos.datasource.xa.XAResourceTransaction]XAResource.rollback ( 636F6D2E61746F6D696B6F732E737072696E672E6A6462632E746D313439323339343330373730353030303035:636F6D2E61746F6D696B6F732E737072696E672E6A6462632E746D35 ) on resource master1 represented by XAResource instance com.mysql.jdbc.jdbc2.optional.JDBC4MysqlXAConnection@2c7e446d
[DEBUG][2017-04-17 09:58:27,906][com.atomikos.icatch.imp.CompositeTransactionImp]rollback() done of transaction com.atomikos.spring.jdbc.tm149239430770500005
[DEBUG][2017-04-17 09:58:27,907][com.atomikos.icatch.imp.CompositeTransactionImp]rollback() done of transaction com.atomikos.spring.jdbc.tm149239430770500005

   

Finally, a reminder that business-related methods must not catch exceptions or throw RunTimeException, otherwise atomikos cannot be rolled back for unknown reasons.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326459551&siteId=291194637