`

spring+mybatis+atomikos 实现JTA事务

 
阅读更多
sping配置多个数据源 不同用户操作不同数据库 http://www.oschina.net/code/snippet_2287006_56769


1:spring3.0之后不再支持jtom[jta]了,第三方开源软件atomikos(http://www.atomikos.com/)来实现.
2:org.springframework.transaction.jta.JotmFactoryBean类,spring-tx-2.5.6.jar中有此类,spring-tx-3.0.0.RELEASE.jar之后没有此类。
3:atomikos事务控制框架,其中看到有3种数据源,分别是,SimpleDataSourceBean,AtomikosDataSourceBean,AtomikosNonXADataSourceBean。
   a:SimpleDataSourceBean: 这个是最简单地数据源配置,需要配置XA驱动。
   b:AtomikosDataSourceBean:  分布式数据源,Atomikos实现的数据源,需要配置XA驱动,推荐此配置,可以配置连接池的信息。
   c:AtomikosNonXADataSourceBean: 非分布式数据源,该数据源配置需要普通JDBC的驱动,可以配置连接池:
4:Atomikos支持XA(全局事务)和NON-XA(非全局事务),NON-XA[nonxadatasource]效率高于XA.XA事务往往是包括多个数据源的全局事务,非XA是单个数据源的.
5:XA连接是一个JTA事务中的参与者。XA连接不支持JDBC的自动提交特性。也就是说应用程序不必在xadatasource[XA]连接上调用



jta.properties
com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactory  
com.atomikos.icatch.console_file_name = /home/pandy/astomikos/tx.out.log  
com.atomikos.icatch.log_base_name = txlog  
com.atomikos.icatch.tm_unique_name = com.atomikos.spring.jdbc.tm  
com.atomikos.icatch.console_log_level=DEBUG  
com.atomikos.icatch.max_timeout=30000  
com.atomikos.icatch.default_jta_timeout=30000


第一方式: 原生的Atomikos
spring+mybatis+Atomikos JTA事务配置说明 http://lizhao6210-126-com.iteye.com/blog/1958831
<dependency>  
    <groupId>com.atomikos</groupId>  
    <artifactId>transactions</artifactId>  
    <!--<version>4.0.2</version>-->  
    <version>3.9.3</version>  
</dependency>  
<dependency>  
    <groupId>com.atomikos</groupId>  
    <artifactId>transactions-api</artifactId>  
    <!--<version>4.0.2</version>-->  
    <version>3.9.3</version>  
</dependency>  
<dependency>  
    <groupId>com.atomikos</groupId>  
    <artifactId>atomikos-util</artifactId>  
    <!--<version>4.0.2</version>-->  
    <version>3.9.3</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.2</version>-->  
    <version>3.9.3</version>  
</dependency>  
<dependency>  
    <groupId>com.atomikos</groupId>  
    <artifactId>transactions-jdbc</artifactId>  
    <!--<version>4.0.2</version>-->  
    <version>3.9.3</version>  
</dependency> 




db.properties 
#单数据库方式, 第一个数据库  
jdbc.driver=com.mysql.jdbc.Driver  
jdbc.url=jdbc:mysql://192.168.0.198:3306/pandy_psi?useUnicode=true&characterEncoding=utf8  
jdbc.username=pandy  
jdbc.password=111111  
  
#多数据库方式  
jdbc.xaDataSourceClassName=com.mysql.jdbc.jdbc2.optional.MysqlXADataSource  
#第二个数据库  
jdbc.url1=jdbc:mysql://192.168.0.198:3306/zhenh5?useUnicode=true&characterEncoding=utf8  
  
  
transactionManager.forceShutdown =true  
transactionManager.transactionTimeout=3000    
#*********************atomikos连接池参数设置*****************************    
#连接池中保留的最小连接数    
atomikos.minPoolSize=5  
#连接池中保留的最大连接数     
atomikos.maxPoolSize=50  
#最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0     
atomikos.maxIdleTime=60
  



applicationContext-mybatis-atomikos.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:xsi="http://www.w3.org/2001/XMLSchema-instance"  
       xmlns:aop="http://www.springframework.org/schema/aop"  
       xsi:schemaLocation="http://www.springframework.org/schema/beans  
        http://www.springframework.org/schema/beans/spring-beans.xsd  
        http://www.springframework.org/schema/aop  
        http://www.springframework.org/schema/aop/spring-aop.xsd  
        http://www.springframework.org/schema/tx  
        http://www.springframework.org/schema/tx/spring-tx.xsd">  
    <!-- 第一个数据库 -->  
    <bean id="dataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean"  
          init-method="init" destroy-method="close">  
        <property name="uniqueResourceName" value="dataSource" />  
        <property name="xaDataSourceClassName" value="${jdbc.xaDataSourceClassName}" />  
        <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="${atomikos.minPoolSize}" />  
        <property name="maxPoolSize" value="${atomikos.maxPoolSize}" />  
        <property name="maxIdleTime" value="${atomikos.maxIdleTime}" />  
    </bean>  
    <!-- 第二个数据库 -->  
    <bean id="dataSourceB" class="com.atomikos.jdbc.AtomikosDataSourceBean"  
          init-method="init" destroy-method="close">  
        <property name="uniqueResourceName" value="dataSourceB" />  
        <property name="xaDataSourceClassName" value="${jdbc.xaDataSourceClassName}" />  
        <property name="xaProperties">  
            <props>  
                <prop key="user">${jdbc.username}</prop>  
                <prop key="password">${jdbc.password}</prop>  
                <prop key="url">${jdbc.url1}</prop>  
            </props>  
        </property>  
        <property name="minPoolSize" value="${atomikos.minPoolSize}" />  
        <property name="maxPoolSize" value="${atomikos.maxPoolSize}" />  
        <property name="maxIdleTime" value="${atomikos.maxIdleTime}" />  
    </bean>  
  
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">  
        <property name="basePackage" value="com.pandy.framework.base.comm.bean,com.pandy.framework.base.atomikos.bean,com.pandy.app.bean,com.pandy.web.bean,com.pandy.weixin.bean,com.pandy.psi.bean" />  
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>  
    </bean>  
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">  
        <property name="basePackage" value="com.pandy.framework.base.atomikos.bean1" />  
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryB"/>  
    </bean>  
  
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" name="sqlSessionFactory">  
        <property name="dataSource" ref="dataSource"/>  
        <property name="mapperLocations" value="classpath*:com/**/bean/**/*Mapper.xml"/>  
        <property name="typeAliasesPackage"  
                  value="com.pandy.framework.base.comm.bean,com.pandy.framework.base.atomikos.bean,com.pandy.app.bean,com.pandy.web.bean,com.pandy.weixin.bean,com.pandy.psi.bean"></property>  
        <property name="plugins">  
            <array>  
                <bean class="com.github.pagehelper.PageHelper">  
                    <property name="properties">  
                        <value>  
                            dialect=mysql  
                        </value>  
                    </property>  
                </bean>  
            </array>  
        </property>  
    </bean>  
  
    <bean id="sqlSessionFactoryB" class="org.mybatis.spring.SqlSessionFactoryBean" name="sqlSessionFactoryB">  
        <property name="dataSource" ref="dataSourceB"/>  
        <property name="mapperLocations" value="classpath*:com/**/bean1/**/*Mapper.xml"/>  
        <property name="typeAliasesPackage"  
                  value="com.pandy.framework.base.atomikos.bean1"></property>  
        <property name="plugins">  
            <array>  
                <bean class="com.github.pagehelper.PageHelper">  
                    <property name="properties">  
                        <value>  
                            dialect=mysql  
                        </value>  
                    </property>  
                </bean>  
            </array>  
        </property>  
    </bean>  
  
    <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">  
        <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory" />  
    </bean>  
    <bean id="sqlSessionTemplateB" class="org.mybatis.spring.SqlSessionTemplate">  
        <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactoryB" />  
    </bean>  
  
    <!-- 定义事务 -->  
    <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:annotation-driven transaction-manager="springTransactionManager" proxy-target-class="true"/>  
</beans>
 



第二种方式:Atomikos + Druid
atomikos支持一个分布式事务,结合spring,可以很好的满足一个应用访问多个库的需要。
Spring多数据源分布式事务管理/springmvc+spring+atomikos[jta]+druid+mybatis http://www.codexiu.cn/mysql/blog/10637/, 这里有bean继承方式配置, 配置有所修改: 执行成功之后, 记录数多的时候很慢,超过10w条记录,可能会出现连接关闭异常

maven
    <dependency>
        <groupId>com.atomikos</groupId>
        <artifactId>transactions</artifactId>
        <version>4.0.2</version>
    </dependency>
    <dependency>
        <groupId>com.atomikos</groupId>
        <artifactId>transactions-api</artifactId>
        <version>4.0.2</version>
    </dependency>
    <dependency>
        <groupId>com.atomikos</groupId>
        <artifactId>atomikos-util</artifactId>
        <version>4.0.2</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.2</version>
    </dependency>
    <dependency>
        <groupId>com.atomikos</groupId>
        <artifactId>transactions-jdbc</artifactId>
        <version>4.0.2</version>
    </dependency>



db.properties
#帐号和密码
jdbc.username=pandy
jdbc.password=111111
validationQuery=SELECT 1

#第一个数据库
jdbc.url=jdbc:mysql://192.168.0.198:3306/pandy_psi?useUnicode=true&characterEncoding=utf8

#第二个数据库
jdbc.url1=jdbc:mysql://192.168.0.198:3306/zhenh5?useUnicode=true&characterEncoding=utf8

#多数据库方式2 Atomikos + Druid
jdbc.driver=org.gjt.mm.mysql.Driver
jdbc.xaDataSourceClassName=com.alibaba.druid.pool.xa.DruidXADataSource


transactionManager.forceShutdown =true
transactionManager.transactionTimeout=3000  
#*********************atomikos连接池参数设置*****************************  
#连接池中保留的最小连接数  
atomikos.minPoolSize=5
#连接池中保留的最大连接数   
atomikos.maxPoolSize=50
#最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0   
atomikos.maxIdleTime=60


applicationContext-mybatis-atomikos-druid.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:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd">

    <bean id="abstractXADataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" lazy-init="true" init-method="init" destroy-method="close" abstract="true">
        <property name="xaDataSourceClassName" value="${jdbc.xaDataSourceClassName}"/>  <!-- SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase, Hana]  -->
        <property name="poolSize" value="15" />
        <property name="minPoolSize" value="10"/>
        <property name="maxPoolSize" value="20"/>
        <property name="borrowConnectionTimeout" value="60"/>
        <property name="reapTimeout" value="20"/>
        <property name="maxIdleTime" value="60"/>
        <property name="maintenanceInterval" value="60"/>
        <property name="loginTimeout" value="60"/>
        <property name="testQuery" value="${validationQuery}"/>
    </bean>

    <!-- 第一个数据库 -->
    <bean id="dataSource" parent="abstractXADataSource">
        <property name="uniqueResourceName" value="dataSource" />
        <property name="xaProperties">
            <props>
                <prop key="driverClassName">${jdbc.driver}</prop>
                <prop key="url">${jdbc.url}</prop>
                <prop key="password">${jdbc.password}</prop>
                <prop key="username">${jdbc.username}</prop>   <!-- durid -->
                <prop key="initialSize">0</prop>
                <prop key="maxActive">20</prop> <!-- 若不配置则代码执行"{dataSource-1} inited"此处停止  -->
                <prop key="minIdle">0</prop>
                <prop key="maxWait">60000</prop>
                <prop key="validationQuery">${validationQuery}</prop>
                <prop key="testOnBorrow">false</prop>
                <prop key="testOnReturn">false</prop>
                <prop key="testWhileIdle">true</prop>
                <prop key="removeAbandoned">true</prop>
                <prop key="removeAbandonedTimeout">1800</prop>
                <prop key="logAbandoned">true</prop>
                <prop key="filters">mergeStat</prop>
            </props>
        </property>
    </bean>
    <!-- 第二个数据库 -->
    <bean id="dataSourceB" parent="abstractXADataSource">
        <property name="uniqueResourceName" value="dataSourceB" />
        <property name="xaProperties">
            <props>
                <prop key="driverClassName">${jdbc.driver}</prop>
                <prop key="url">${jdbc.url1}</prop>
                <prop key="password">${jdbc.password}</prop>
                <prop key="username">${jdbc.username}</prop>
                <prop key="initialSize">0</prop>
                <prop key="maxActive">20</prop>
                <prop key="minIdle">0</prop>
                <prop key="maxWait">60000</prop>
                <prop key="validationQuery">${validationQuery}</prop>
                <prop key="testOnBorrow">false</prop>
                <prop key="testOnReturn">false</prop>
                <prop key="testWhileIdle">true</prop>
                <prop key="removeAbandoned">true</prop>
                <prop key="removeAbandonedTimeout">1800</prop>
                <prop key="logAbandoned">true</prop>
                <prop key="filters">mergeStat</prop>
            </props>
        </property>
    </bean>

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.pandy.framework.base.comm.bean,com.pandy.framework.base.atomikos.bean,com.pandy.app.bean,com.pandy.web.bean,com.pandy.weixin.bean,com.pandy.psi.bean" />
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.pandy.framework.base.atomikos.bean1" />
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryB"/>
    </bean>

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" name="sqlSessionFactory">
        <property name="dataSource" ref="dataSource"/>
        <property name="mapperLocations" value="classpath*:com/**/bean/**/*Mapper.xml"/>
        <property name="typeAliasesPackage"
                  value="com.pandy.framework.base.comm.bean,com.pandy.framework.base.atomikos.bean,com.pandy.app.bean,com.pandy.web.bean,com.pandy.weixin.bean,com.pandy.psi.bean"></property>
        <property name="plugins">
            <array>
                <bean class="com.github.pagehelper.PageHelper">
                    <property name="properties">
                        <value>
                            dialect=mysql
                        </value>
                    </property>
                </bean>
            </array>
        </property>
    </bean>

    <bean id="sqlSessionFactoryB" class="org.mybatis.spring.SqlSessionFactoryBean" name="sqlSessionFactoryB">
        <property name="dataSource" ref="dataSourceB"/>
        <property name="mapperLocations" value="classpath*:com/**/bean1/**/*Mapper.xml"/>
        <property name="typeAliasesPackage"
                  value="com.pandy.framework.base.atomikos.bean1"></property>
        <property name="plugins">
            <array>
                <bean class="com.github.pagehelper.PageHelper">
                    <property name="properties">
                        <value>
                            dialect=mysql
                        </value>
                    </property>
                </bean>
            </array>
        </property>
    </bean>

    <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory" />
    </bean>
    <bean id="sqlSessionTemplateB" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactoryB" />
    </bean>

    <!-- 定义事务 -->
    <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:annotation-driven transaction-manager="springTransactionManager" proxy-target-class="true"/>
</beans>






对非主数据库的DAO, 要手动注入相应的SqlSessionTemplate

配置方式: 推荐这种方式
applicationContext-mybatis-atomikos-dao.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:xsi="http://www.w3.org/2001/XMLSchema-instance"  
       xmlns:aop="http://www.springframework.org/schema/aop"  
       xsi:schemaLocation="http://www.springframework.org/schema/beans  
        http://www.springframework.org/schema/beans/spring-beans.xsd  
        http://www.springframework.org/schema/aop  
        http://www.springframework.org/schema/aop/spring-aop.xsd  
        http://www.springframework.org/schema/tx  
        http://www.springframework.org/schema/tx/spring-tx.xsd">  
    <!-- 因为这里使用了第二个数据库, 所以不能使用注解, 注解会注入sqlSessionTemplate, 而不是注入sqlSessionTemplateB, 会提示找不到Mapped Statements  -->  
    <bean id="testAtomikosBDao" class="com.pandy.framework.base.atomikos.dao.impl.TestAtomikosBDaoImpl">  
        <property name="sqlSessionTemplate" ref="sqlSessionTemplateB"/>  
    </bean>  
</beans>
 


注解方式: 为测试, 可能无法使用这种方式 
@Repository("testAtomikosBDao")  
public class TestAtomikosBDaoImpl{  
    @Resource(name="sqlSessionTemplateB")  
    private SqlSessionTemplate sqlSessionTemplate;  
}  
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics