您好,登錄后才能下訂單哦!
怎么在spring中使用atomikos實現分布式事務?針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
項目結構
從web.xml中可以知道,容器只加載了appliactionContext.xml,剩下的配置文件除了database.properties外都是無用文件,所以大家如果要在項目中配置的話,僅需要把appliactionContext.xml中關于atomikos的部分新增到自己項目中就OK了
appliactionContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <!-- 引入數據源信息的properties屬性文件 --> <context:property-placeholder location="classpath:database.properties" /> <!-- XA方式 --> <!-- MYSQL數據庫配置 --> <bean id="mysqlDataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" destroy-method="close"> <property name="uniqueResourceName" value="dataSource1"/> <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"/> <property name="xaProperties"> <props> <prop key="URL">${mysql.qa.db.url}</prop> <prop key="user">${mysql.qa.db.user}</prop> <prop key="password">${mysql.qa.db.password}</prop> </props> </property> <property name="minPoolSize" value="10" /> <property name="maxPoolSize" value="100" /> <property name="borrowConnectionTimeout" value="30" /> <property name="maintenanceInterval" value="60" /> </bean> <!-- ORACLE數據庫配置 --> <bean id="oracleDataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" destroy-method="close"> <property name="uniqueResourceName" value="dataSource2"/> <property name="xaDataSourceClassName" value="oracle.jdbc.xa.client.OracleXADataSource" /> <property name="xaProperties"> <props> <prop key="URL">${oracle.qa.db.url}</prop> <prop key="user">${oracle.qa.db.user}</prop> <prop key="password">${oracle.qa.db.password}</prop> </props> </property> <property name="minPoolSize" value="10" /> <property name="maxPoolSize" value="100" /> <property name="borrowConnectionTimeout" value="30" /> <property name="maintenanceInterval" value="60" /> </bean> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!--<property name="configLocation" value="classpath:mybatis-config-mysql.xml" />--> <property name="dataSource" ref="mysqlDataSource" /> <property name="mapperLocations" > <list> <value>classpath*:/dao/*.xml</value> </list> </property> </bean> <bean id="sqlSessionFactoryOracle" class="org.mybatis.spring.SqlSessionFactoryBean"> <!--<property name="configLocation" value="classpath:mybatis-config.xml" />--> <property name="dataSource" ref="oracleDataSource" /> <property name="mapperLocations" > <list> <value>classpath*:/daodev/*.xml</value> </list> </property> </bean> <!-- MyBatis為不同的mapper注入sqlSessionFactory --> <bean id="mysqlTransactionTestDao" class="org.mybatis.spring.mapper.MapperFactoryBean"> <property name="sqlSessionFactory" ref="sqlSessionFactory" /> <property name="mapperInterface" value="com.xy.dao.MysqlTransactionTestDao" /> </bean> <bean id="transactionTestDao" class="org.mybatis.spring.mapper.MapperFactoryBean"> <property name="sqlSessionFactory" ref="sqlSessionFactoryOracle" /> <property name="mapperInterface" value="com.xy.dao.TransactionTestDao" /> </bean> <!-- 分布式事務 --> <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close"> <property name="forceShutdown" value="true"/> </bean> <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"> <property name="transactionTimeout" value="300"/> </bean> <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <property name="transactionManager" ref="atomikosTransactionManager"/> <property name="userTransaction" ref="atomikosUserTransaction"/> </bean> <tx:annotation-driven transaction-manager="transactionManager"/> <context:annotation-config/> <!--<!– 自動掃描controller包下的所有類,如果@Controller注入為bean –>--> <!--<!–事務管理層–>--> <context:component-scan base-package="com.xy" /> <!-- 注冊攔截器 --> <!--<mvc:interceptors> <bean class="com.springmybatis.system.interceptor.MyInterceptor" /> </mvc:interceptors>--> </beans>
適用JUnit4進行單元測試
package com.xy.controller; import com.xy.daodev.TransactionTestService; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; @ContextConfiguration(locations = {"classpath:applicationContext.xml"}) public class TransactionTestMain extends AbstractJUnit4SpringContextTests { @Autowired private TransactionTestService transactionTestService; /** * 在同一事務有多個數據源 */ @Test public void multipleDataSource2() { transactionTestService.updateMultipleDataSource("1","1", 100L,"1.6"); } }
業務實現,當前沒有異常操作
@Service public class TransactionTestServiceImpl implements TransactionTestService { @Autowired @Qualifier("mysqlTransactionTestDao") private MysqlTransactionTestDao mysqlTransactionTestDao; @Autowired @Qualifier("transactionTestDao") private TransactionTestDao transactionTestDao; /** * 在同一事務有多個數據源 */ @Override @Transactional public void updateMultipleDataSource(String deUserId, String inUserid, long money,String str) { // 賬戶1轉出操作 mysqlTransactionTestDao.decreaseMoney(deUserId, money); //Integer.parseInt(str); // 賬戶2轉入操作 transactionTestDao.increaseMoney(inUserid, money); } }
mysql模擬金額轉出,oracle模擬金額轉入
<update id="decreaseMoney" parameterType="java.util.Map"> UPDATE fx1 SET amount=amount - #{1,jdbcType=BIGINT} WHERE id=#{0,jdbcType=VARCHAR} </update>
<update id="increaseMoney"> UPDATE fx1 SET amount=amount + #{1,jdbcType=BIGINT} WHERE id=#{0,jdbcType=VARCHAR} </update>
mysql初始金額
oracle初始金額
執行正常操作
mysql當前金額
oracle當前金額
將被屏蔽的制造異常的代碼打開
public void updateMultipleDataSource(String deUserId, String inUserid, long money,String str) { // 賬戶1轉出操作 mysqlTransactionTestDao.decreaseMoney(deUserId, money); Integer.parseInt("skg"); // 賬戶2轉入操作 transactionTestDao.increaseMoney(inUserid, money); }
發現mysql和oracle的當前金額都沒有變化,說明事務回滾成功,查看日志
關于怎么在spring中使用atomikos實現分布式事務問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。