#1 系列目录java
#2 Atomikos使用非XA数据库驱动实现分布式事务mysql
项目地址见:Atomikos使用非XA数据库驱动实现分布式事务git
##2.1 业务逻辑的操做spring
UserDao和LogDao,操做分别以下:sql
@Repository public class UserDao { @Resource(name="jdbcTemplateA") private JdbcTemplate jdbcTemplate; public void save(User user){ jdbcTemplate.update("insert into user(name,age) values(?,?)",user.getName(),user.getAge()); } } @Repository public class LogDao { @Resource(name="jdbcTemplateB") private JdbcTemplate jdbcTemplate; public void save(User user){ jdbcTemplate.update("insert into log(name,age) values(?,?)",user.getName(),user.getAge()); } }
即上述两个JdbcTemplate使用不一样的数据库。数据库
UserService综合上述两个业务操做,使它们处于同一个事务中:分布式
[@Service](http://my.oschina.net/service) public class UserService { @Autowired private UserDao userDao; @Autowired private LogDao logDao; @Transactional public void save(User user){ userDao.save(user); logDao.save(user); throw new RuntimeException(); } }
##2.2 配置源码分析
上述业务代码咱们看不到分布式事务的存在,这种正是咱们想要的效果,分布式事务对业务透明。究竟是如何来实现呢?atom
###2.2.1 dataSource和JdbcTemplate配置url
<bean id="dataSourceA" class="com.atomikos.jdbc.nonxa.AtomikosNonXADataSourceBean" init-method="init" destroy-method="close"> <property name="uniqueResourceName" value="XA1DBMS" /> <property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8" /> <property name="user" value="root" /> <property name="password" value="xxxx" /> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="poolSize" value="3" /> <property name="minPoolSize" value="3" /> <property name="maxPoolSize" value="5" /> </bean> <bean id="dataSourceB" class="com.atomikos.jdbc.nonxa.AtomikosNonXADataSourceBean" init-method="init" destroy-method="close"> <property name="uniqueResourceName" value="XA2DBMS" /> <property name="url" value="jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8" /> <property name="user" value="root" /> <property name="password" value="xxxx" /> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="poolSize" value="3" /> <property name="minPoolSize" value="3" /> <property name="maxPoolSize" value="5" /> </bean> <bean id="jdbcTemplateA" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSourceA" /> </bean> <bean id="jdbcTemplateB" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSourceB" /> </bean>
自行配置2个数据库地址
咱们日常使用的dataSource,大部分是c3p0、dbcp等,这里就不能使用它们了,须要换成能够模拟XA协议的dataSource,这里即AtomikosNonXADataSourceBean。
###2.2.2 事务配置
咱们知道分布式事务中须要一个事务管理器即接口javax.transaction.TransactionManager、面向开发人员的javax.transaction.UserTransaction。对于Atomikos来讲分别对应以下:
咱们若是想使用分布式事务的同时,又想使用Spring带给咱们的@Transactional便利,就须要配置一个JtaTransactionManager,而该JtaTransactionManager是须要一个userTransaction实例的
<bean id="userTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"> <property name="transactionTimeout" value="300" /> </bean> <bean id="springTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <property name="userTransaction" ref="userTransaction" /> </bean> <tx:annotation-driven transaction-manager="springTransactionManager"/>
能够对比下jotm的案例配置jotm的分布式事务配置。能够看到jotm中使用的xapool中的StandardXADataSource是须要一个transactionManager的,而Atomikos使用的AtomikosNonXADataSourceBean则不须要。咱们知道,StandardXADataSource中有了transactionManager就能够获取当前线程的事务,同时把XAResource加入进当前事务中去,而AtomikosNonXADataSourceBean却没有,它是怎么把XAResource加入进当前线程绑定的事务呢?这时候就须要能够经过静态方法随时获取当前线程绑定的事务。
###2.2.3 jar包依赖
这里只使用了Atomikos,不像jotm还使用了xapool。
<!-- atomikos --> <dependency> <groupId>com.atomikos</groupId> <artifactId>transactions-jdbc</artifactId> <version>4.0.0M4</version> </dependency>
#3 Atomikos使用XA数据库驱动实现分布式事务
项目地址见:Atomikos使用非XA数据库驱动实现分布式事务
##3.1 业务逻辑的操做
UserDao和LogDao,操做分别以下:
@Repository public class UserDao { @Resource(name="jdbcTemplateA") private JdbcTemplate jdbcTemplate; public void save(User user){ jdbcTemplate.update("insert into user(name,age) values(?,?)",user.getName(),user.getAge()); } } @Repository public class LogDao { @Resource(name="jdbcTemplateB") private JdbcTemplate jdbcTemplate; public void save(User user){ jdbcTemplate.update("insert into log(name,age) values(?,?)",user.getName(),user.getAge()); } }
即上述两个JdbcTemplate使用不一样的数据库。
UserService综合上述两个业务操做,使它们处于同一个事务中:
@Service public class UserService { @Autowired private UserDao userDao; @Autowired private LogDao logDao; @Transactional public void save(User user){ userDao.save(user); logDao.save(user); throw new RuntimeException(); } }
##3.2 配置
上述业务代码咱们看不到分布式事务的存在,这种正是咱们想要的效果,分布式事务对业务透明。究竟是如何来实现呢?
###3.2.1 dataSource和JdbcTemplate配置
<bean id="dataSourceA" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close"> <property name="uniqueResourceName" value="XA1DBMS" /> <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" /> <property name="xaProperties"> <props> <prop key="URL">jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8</prop> <prop key="user">root</prop> <prop key="password">ligang</prop> </props> </property> <property name="poolSize" value="3" /> <property name="minPoolSize" value="3" /> <property name="maxPoolSize" value="5" /> </bean> <bean id="dataSourceB" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close"> <property name="uniqueResourceName" value="XA2DBMS" /> <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" /> <property name="xaProperties"> <props> <prop key="URL">jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8</prop> <prop key="user">root</prop> <prop key="password">ligang</prop> </props> </property> <property name="poolSize" value="3" /> <property name="minPoolSize" value="3" /> <property name="maxPoolSize" value="5" /> </bean>
自行配置上述2个数据库地址
咱们日常使用的dataSource,大部分是c3p0、dbcp等,这里就不能使用它们了,须要换成能够Atomikos本身的dataSource,这里即AtomikosDataSourceBean。它须要使用支持XA的jdbc驱动。具体就是须要一个xaDataSourceClassName,咱们这里使用的是mysql支持xa的的MysqlXADataSource,它实现了javax.sql.XADataSource接口,便可以产生XAConnection链接。
Atomikos使用非XA数据库驱动实现分布式事务 与 Atomikos使用XA数据库驱动实现分布式事务惟一配置上的不一样就是这里的dataSource配置,其余内容都同样。
###3.2.2 事务配置
咱们知道分布式事务中须要一个事务管理器即接口javax.transaction.TransactionManager、面向开发人员的javax.transaction.UserTransaction。对于Atomikos来讲分别对应以下:
咱们若是想使用分布式事务的同时,又想使用Spring带给咱们的@Transactional便利,就须要配置一个JtaTransactionManager,而该JtaTransactionManager是须要一个userTransaction实例的
<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="userTransaction" ref="atomikosUserTransaction" /> </bean> <tx:annotation-driven transaction-manager="springTransactionManager"/>
###3.2.3 jar包依赖
这里只使用了Atomikos,不像jotm还使用了xapool。
<!-- atomikos --> <dependency> <groupId>com.atomikos</groupId> <artifactId>transactions-jdbc</artifactId> <version>4.0.0M4</version> </dependency>
#4 结束语
本文介绍了Atomikos使用XA数据库驱动和非XA数据库驱动两种方式来实现分布式事务的案例,下一篇文章就来详细说明下其中的原理。