SpringMvc + Mybatis項目中 使用 Atomikos實現分布式事務


背景:項目架構使用了SpringMvc + Mybatis,同時在使用多數據源的時候需要滿足事務一致性

  通俗的說法是:項目中配置了多個數據源,並且在一個service方法中使用多個數據源的時候需要保證事務一致性。

  網上的主流資料大概講解了兩種spring對分布式事務的實現:jotm和Atomikos,需要注意的是使用jotm的時候需要用到一個類org.springframework.transaction.jta.JotmFactoryBean然而在spring 3.x之后移除了這個類,所以我采用了Atomikos的方式。

  實現過程如下:

  1、在使用了Atomikos之后需要注意DataSource不能再使用c3p0 之類的驅動了,需要用到com.atomikos.jdbc.AtomikosDataSourceBean,下面是兩個DataSource的配置示例:

  

 1 <bean id="dataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">
 2         <property name="uniqueResourceName" value="XA1DBMS1" />  
 3         <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />  
 4         <property name="xaProperties">  
 5             <props>  
 6                 <prop key="URL">${dataPortal_mysql_jdbc_url}</prop>  
 7                 <prop key="user">${dataPortal_mysql_jdbc_user}</prop>  
 8                 <prop key="password">${dataPortal_mysql_jdbc_password}</prop>  
 9             </props>  
10         </property>  
11         <property name="poolSize" value="3" />  
12         <property name="minPoolSize" value="3" />  
13         <property name="maxPoolSize" value="5" />
14     </bean>
15     
16     <bean id="webDataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">
17         <property name="uniqueResourceName" value="XA1DBMS2" />  
18         <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />  
19         <property name="xaProperties">  
20             <props>  
21                 <prop key="URL">${web.jdbc.url}</prop>  
22                 <prop key="user">${web.jdbc.username}</prop>  
23                 <prop key="password">${web.jdbc.password}</prop>  
24             </props>  
25         </property>  
26         <property name="poolSize" value="3" />  
27         <property name="minPoolSize" value="3" />  
28         <property name="maxPoolSize" value="5" />
29     </bean>

 這里一些其他的參數,比如最大連接數,超時時間的參數我是在com.atomikos.jdbc.AtomikosDataSourceBean源碼中找到的:

 

兩個DataSource中webDataSource我采用的是spring的JdbcTemplate去寫sql而dataSource則配置使用了mybatis的方式

2、兩種不同的方式配置如下:

 1 <!-- web庫jdbcTemplate -->
 2     <bean id="webJdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
 3         <property name="dataSource" ref="webDataSource" />
 4     </bean>
 5     <!-- gmt庫jdbcTemplate -->
 6     <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
 7         <property name="dataSource">
 8             <ref bean="dataSource" />
 9         </property>
10     </bean>
11     
12     <!-- 創建SqlSessionFactory,同時指定數據源 -->
13     <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
14         <property name="dataSource" ref="dataSource" />
15         <property name="mapperLocations"  value="classpath:com/sincetimes/modernship/**/dao/*.xml"/>
16     </bean>
17     
18     <!-- mybatis自動掃描器 -->
19     <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
20         <property name="basePackage" value="com.sincetimes.modernship.dao" />
21         <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
22     </bean>
23     
24     <!-- DAO使用mybatis進行數據庫訪問操作 -->
25     <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
26         <constructor-arg index="0" ref="sqlSessionFactory" />
27     </bean>

3、在配置事務的時候,我們可以使用@Transactional注解,也可以寫aop

 1 <!-- 分布式事務 -->
 2     <bean id="userTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">  
 3         <property name="transactionTimeout" value="300" />  
 4     </bean>  
 5 
 6     <bean id="springTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">  
 7         <property name="userTransaction" ref="userTransaction" />   
 8     </bean>
 9 
10     <tx:annotation-driven transaction-manager="springTransactionManager"/>
11 
12     <aop:config>
13         <aop:pointcut id="baseServiceMethods" expression="execution(* com.sincetimes..impl..*.*(..))" />
14         <aop:advisor pointcut-ref="baseServiceMethods" advice-ref="txAdvice"/>
15     </aop:config>
16 
17     <!-- 配置事務的傳播特性 -->
18     <tx:advice id="txAdvice" transaction-manager="springTransactionManager">
19         <tx:attributes>
20             <tx:method name="query*" propagation="REQUIRED" read-only="true" />
21             <tx:method name="get*" propagation="REQUIRED" read-only="true" />
22             <tx:method name="find*" propagation="REQUIRED" read-only="true" />
23             <tx:method name="list*" propagation="REQUIRED" read-only="true" />
24             <tx:method name="count*" propagation="REQUIRED" read-only="true" />
25             <tx:method name="insert*" propagation="REQUIRED" />
26             <tx:method name="add*" propagation="REQUIRED" />
27             <tx:method name="del*" propagation="REQUIRED" />
28             <tx:method name="save*" propagation="REQUIRED" />
29             <tx:method name="update*" propagation="REQUIRED" />
30             <tx:method name="edit*" propagation="REQUIRED" />
31             <tx:method name="enable*" propagation="REQUIRED" />                
32             <tx:method name="upload*" propagation="REQUIRED" />                
33         </tx:attributes>
34     </tx:advice>

分布式事務中的重點是事務管理器。在Atomikos中對應的就是 com.atomikos.icatch.jta.UserTransactionManager 

4、如果項目使用了log4j的話,並且日志級別為info,在項目啟動后會發現有很多atomikos的info日志打印出來,這個時候在log4j的配置文件中增加一個配置:log4j.logger.com.atomikos = error 即可。

這里參考了網上找到的資料:https://my.oschina.net/pingpangkuangmo/blog/413518

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM