使用Atomikos Transactions Essentials實現多資料來源JTA分散式事務
宣告:本片文章來源於開源社群論壇轉載~!奮鬥
使用NonXADataSourceBean. Mysql在5.0版本和Connecter/J5.0版本後提供了XADatasource支援,如果使用了支援XADatasouce版本
最近做的project中遇到要將資料庫中的表分佈到兩臺不同的伺服器上的Mysql5.0中,project主要使用spring+ibatis。因此需要JTA的支援,但是tomcat不支援,所以就搜尋開源的JTA實現。
最開始使用的是JOTM,但是使用中不能自動rollback,無論什麼情況都commit。然後看到infoq上一篇文章提到Atomikos Transactions Essentials,Atomikos Transactions Essentials 3.0是Atomikos 開發的核心事務引擎,支援JDBC 以及JMS 的JTA/XA 事務。易於部署,輕量級,同時支援JDBC 以及JMS 。
Atomikos Transactions Essentials現在的版本是3.1.7,可以在
<!-- 第一個資料庫 -->
< bean id = "dataSource" class = "com.atomikos.jdbc.SimpleDataSourceBean" init-method = "init" destroy-method = "close" >
<property name="uniqueResourceName">
<value> mysql/main </value>
</property>
<property name = "xaDataSourceClassName ">
<!-- 使用Mysql XADataSource(mysql>=5.0, Connector/J>=5.0才可以支援XADatasource)-->
<value > com.mysql.jdbc.jdbc2.optional.MysqlXADataSource </ value >
</ property >
< property name = "xaDataSourceProperties" >
< value > URL =${jdbc.url}; user =${jdbc.username}; password =${jdbc.password} </ value >
</ property >
< property name = "exclusiveConnectionMode" >
< value > true </ value >
</ property >
< property name = "connectionPoolSize" >
< value > 3 </ value >
</ property >
< property name = "validatingQuery" >
< value > SELECT 1 </ value >
</ property >
</ bean >
<!-- 第二個資料庫 -->
< bean id = "dataSourceB" class = "com.atomikos.jdbc.SimpleDataSourceBean" init-method = "init" destroy-method = "close" >
< property name = "uniqueResourceName" >
< value > mysql/news </ value >
</ property >
< property name = "xaDataSourceClassName" >
<!-- 使用Mysql XADataSource(mysql>=5.0, Connector/J>=5.0才可以支援XADatasource)-->
< value > com.mysql.jdbc.jdbc2.optional.MysqlXADataSource </ value >
</ property >
< property name = "xaDataSourceProperties" >
< value > URL =${jdbc.url.b}; user =${jdbc.username.b}; password =${jdbc.password.b} </ value >
</ property >
< property name = "exclusiveConnectionMode" >
< value > true </ value >
</ property >
< property name = "connectionPoolSize" >
< value > 3 </ value >
</ property >
< property name = "validatingQuery" >
< value > SELECT 1 </ value >
</ property >
</ bean >
< bean id = "lobHandler" class = "org.springframework.jdbc.support.lob.DefaultLobHandler" />
<!-- 第一個資料庫的sqlMapClient -->
< bean id = "sqlMapClient" class = "org.springframework.orm.ibatis.SqlMapClientFactoryBean" >
< property name = "configLocation" >
<!-- 包含第一個資料庫表的map -->
< value > classpath:/sqlmap-config.xml </ value >
</ property >
< property name = "dataSource" ref = "dataSource" />
< property name = "lobHandler" ref = "lobHandler" />
</ bean >
<!-- 第二個資料庫的sqlMapClient -->
< bean id = "sqlMapClientB" class = "org.springframework.orm.ibatis.SqlMapClientFactoryBean" >
< property name = "configLocation" >
<!-- 包含第一個資料庫表的map -->
< value > classpath:/sqlmap-configb.xml </ value >
</ property >
< property name = "dataSource" ref = "dataSourceB" />
< property name = "lobHandler" ref = "lobHandler" />
</ bean >
<!-- Construct Atomikos UserTransactionManager, needed to configure Spring -->
< bean id = "atomikosTransactionManager" class = "com.atomikos.icatch.jta.UserTransactionManager" init-method = "init"
destroy-method = "close" >
<!-- when close is called, should we force transactions to terminate or not? -->
< property name = "forceShutdown" >
< value > true </ value >
</ property >
</ bean >
<!-- Also use Atomikos UserTransactionImp, needed to configure Spring -->
< bean id = "atomikosUserTransaction" class = "com.atomikos.icatch.jta.UserTransactionImp" >
< property name = "transactionTimeout" value = "240" />
</ bean >
<!-- Configure the Spring framework to use JTA transactions from Atomikos -->
< bean id = "transactionManager" class = "org.springframework.transaction.jta.JtaTransactionManager" >
< property name = "transactionManager" >
< ref bean = "atomikosTransactionManager" />
</ property >
< property name = "userTransaction" >
< ref bean = "atomikosUserTransaction" />
</ property >
</ bean >
事務的配置, 使用了spring2.0的語法,所以將namesapce也帖出來了.
<? 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:aop = "http://www.springframework.org/schema/aop"
xmlns:tx = "http://www.springframework.org/schema/tx"
xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"
default-autowire = "byName" default-lazy-init = "true" >
<!-- 支援 @AspectJ 標記-->
< aop:aspectj-autoproxy />
< aop:config proxy-target-class = "true" >
< aop:advisor pointcut = "execution(* *Facade.*(..))" advice-ref = "txAdvice" />
< aop:advisor pointcut = "execution(* *Manager.*(..))" advice-ref = "txAdvice" />
</ aop:config >
< tx:advice id = "txAdvice" >
< tx:attributes >
< tx:method name = "get*" read-only = "true" />
< tx:method name = "find*" read-only = "true" />
< tx:method name = "has*" read-only = "true" />
< tx:method name = "locate*" read-only = "true" />
< tx:method name = "*" />
</ tx:attributes >
</ tx:advice >
</ beans >
這樣配置以後就可以使用分散式事務,測試中出現異常時事務也自動回滾。和JOTM相比Atomikos Transactions Essentials更加穩定,它原來是商業專案,現在開源了。象mysql一樣賣服務支援的。而且論壇頁比較活躍,有問題很快可以解決。