打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Java事务
        JTA是J2EE的规范之一,如果使用JTA,我们需要去实现相应接口。tomcat是web服务器,没有实现J2EE规范,如果我们需要在tomcat服务器使用JTA,需要自己去实现JTA的接口。本文介绍如何使用tomcat+JTA实现多数据源的分布式事务。
        一 选型

tomcat需要使用插件实现JTA,常用插件有jotm和atomikos,本文以atomikos为例。jar如下:

atomikos-util-1.0.jar
cglib-nodep-2.2.2.jar
transactions-3.7.0.jar
transactions-api-3.7.0.jar
transactions-jdbc-3.7.0.jar
transactions-jta-3.7.0.jar

如果是maven项目,POM配置如下:

  1. <span style="white-space:pre">        </span><dependency>  
  2.             <groupId>com.atomikos</groupId>  
  3.             <artifactId>transactions-jdbc</artifactId>  
  4.             <version>3.9.1</version>  
  5.         </dependency>  
  6.         <dependency>  
  7.             <groupId>javax.transaction</groupId>  
  8.             <artifactId>jta</artifactId>  
  9.             <version>1.1</version>  
  10.         </dependency>  
  11.         <dependency>  
  12.             <groupId>cglib</groupId>  
  13.             <artifactId>cglib-nodep</artifactId>  
  14.             <version>3.2.4</version>  
  15.         </dependency>  


        二 配置数据库

        我们使用了两个数据库做测试,模拟多数据源的业务场景。数据库如下:


        两个数据库分别是log和user,每个数据库中创建一张表,分别是log和user,数据库类型都是MySQL(两个数据库类型不一致也可以)。
        三 持久层

        我们直接使用JdbcTemplate实现持久化,代码如下:

  1. <span style="font-size:18px;">public class LogDao extends JdbcDaoSupport {  
  2.     public boolean insertLog(String id, String content) {  
  3.         JdbcTemplate template = getJdbcTemplate();  
  4.         template.execute("insert into log values('" + id + "','" + content + "')");  
  5.         return true;  
  6.     }  
  7. }</span>  
  1. <span style="font-size:18px;">public class UserDao extends JdbcDaoSupport {  
  2.     public boolean insertUser(String id, String name) {  
  3.         JdbcTemplate template = getJdbcTemplate();  
  4.         template.execute("insert into user values('" + id + "','" + name + "')");  
  5.         return true;  
  6.     }  
  7. }</span>  

        持久层创建两个类,每个类添加一个方法,向数据库插入一条记录。
        四 service层

        我们要把事务加到这一层,代码如下:

  1. @Transactional  
  2. public class UserService {  
  3.     private UserDao userDao;  
  4.     private LogDao logDao;  
  5.   
  6.     public void saveUser(String id, String name) {  
  7.         boolean flag1 = userDao.insertUser(id, name);  
  8.         System.out.println("zhang san save success!");  
  9.         int i = 1 / 0;  // 制造异常  
  10.         boolean flag2 = logDao.insertLog(id, id + "_" + name);  
  11.         if(flag1 && flag2){  
  12.             System.out.println("保存成功");  
  13.         }  
  14.         /*boolean flag2 = userDao.insertUser("2","lisi"); 
  15.         System.out.println("li si save success!");*/  
  16.     }  
  17.   
  18.     public UserDao getUserDao() {  
  19.         return userDao;  
  20.     }  
  21.   
  22.     public void setUserDao(UserDao userDao) {  
  23.         this.userDao = userDao;  
  24.     }  
  25.   
  26.     public LogDao getLogDao() {  
  27.         return logDao;  
  28.     }  
  29.   
  30.     public void setLogDao(LogDao logDao) {  
  31.         this.logDao = logDao;  
  32.     }  
  33. }  

        分别调用持久层方法,并且在两次调用中间抛出异常,看数据是否能持久化到数据库。
        五 配置文件

        1 资源管理器配置

  1. <!-- 数据库1 -->  
  2.     <bean id="db1" class="com.atomikos.jdbc.SimpleDataSourceBean" init-method="init" destroy-method="close">     
  3.         <property name="uniqueResourceName">     
  4.             <value>mysql/main</value>     
  5.         </property>     
  6.         <property name="xaDataSourceClassName">     
  7.             <value>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</value>     
  8.         </property>     
  9.         <property name="xaDataSourceProperties">     
  10.             <value>URL=jdbc:mysql://localhost:3306/user?useUnicode=true&characterEncoding=utf-8;user=root;password=123456</value>     
  11.         </property>     
  12.         <property name="exclusiveConnectionMode">     
  13.             <value>true</value>     
  14.         </property>     
  15.         <property name="connectionPoolSize">     
  16.             <value>3</value>     
  17.         </property>     
  18.         <property name="validatingQuery">     
  19.             <value>SELECT 1</value>     
  20.         </property>     
  21.     </bean>         
  22.       
  23.     <!-- 数据库2 -->  
  24.     <bean id="db2" class="com.atomikos.jdbc.SimpleDataSourceBean" init-method="init" destroy-method="close">     
  25.         <property name="uniqueResourceName">     
  26.             <value>mysql/secondary</value>     
  27.         </property>     
  28.         <property name="xaDataSourceClassName">        
  29.             <value>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</value>     
  30.         </property>  
  31.         <property name="xaDataSourceProperties">     
  32.             <value>URL=jdbc:mysql://localhost:3306/log?useUnicode=true&characterEncoding=utf-8;user=root;password=123456</value>     
  33.         </property>  
  34.         <property name="exclusiveConnectionMode">     
  35.             <value>true</value>     
  36.         </property>  
  37.         <property name="connectionPoolSize">     
  38.             <value>3</value>     
  39.         </property>  
  40.         <property name="validatingQuery">  
  41.             <value>SELECT 1</value>     
  42.         </property>     
  43.     </bean>  

        2 持久层注入

  1. <bean id="userDao" class="com.zdp.dao.UserDao">  
  2.     <property name="dataSource" ref="db1" />  
  3. </bean>  
  4.   
  5. <bean id="logDao" class="com.zdp.dao.LogDao">  
  6.     <property name="dataSource" ref="db2" />  
  7. </bean>  
  8.   
  9. <bean id="userService" class="com.zdp.service.UserService">  
  10.     <property name="userDao" ref="userDao" />  
  11.     <property name="logDao" ref="logDao" />              
  12. </bean>  

        3 事务管理器配置

  1. <bean id="userTransactionManager" init-method="init" destroy-method="close"  
  2.     class="com.atomikos.icatch.jta.UserTransactionManager">     
  3.     <property name="forceShutdown" value="true" />     
  4. </bean>  
  5.   
  6. <bean id="userTransactionImp" class="com.atomikos.icatch.jta.UserTransactionImp">     
  7.     <property name="transactionTimeout" value="300"/>      
  8. </bean>  
  9.   
  10. <bean id="jtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">     
  11.     <property name="transactionManager" ref="userTransactionManager" />  
  12.     <property name="userTransaction" ref="userTransactionImp" />  
  13.     <property name="allowCustomIsolationLevels" value="true"/>   
  14. </bean>  

        4 使用AOP管理事务

  1. <tx:advice id="txAdvice" transaction-manager="jtaTransactionManager">  
  2.     <tx:attributes>  
  3.        <tx:method name="save*" propagation="REQUIRED" rollback-for="Exception"/>  
  4.        <tx:method name="add*" propagation="REQUIRED" rollback-for="Exception"/>  
  5.        <tx:method name="create*" propagation="REQUIRED" rollback-for="Exception"/>  
  6.        <tx:method name="insert*" propagation="REQUIRED" rollback-for="Exception"/>  
  7.        <tx:method name="del*" propagation="REQUIRED" rollback-for="Exception"/>  
  8.        <tx:method name="update*" propagation="REQUIRED" rollback-for="Exception"/>  
  9.        <tx:method name="*" read-only="true"/>  
  10.    </tx:attributes>  
  11. </tx:advice>  
  12.   
  13. <!-- 事务管理 -->  
  14. <aop:config proxy-target-class="true">  
  15.     <aop:advisor pointcut="execution(* com.zdp.service..*.*(..))" advice-ref="txAdvice"/>  
  16. </aop:config>  

        六 测试类

  1. public class UserTest {  
  2.     @Test  
  3.     public void testSave() {  
  4.         ApplicationContext cxt = new ClassPathXmlApplicationContext("ApplicationContext.xml");  
  5.         UserService us = (UserService) cxt.getBean("userService");  
  6.         us.saveUser("1", "zhangsan");  
  7.     }  
  8. }  


        七 总结

        经过测试,速度比较慢,如果系统对性能要求较高,不建议使用。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
使用Atomikos Transactions Essentials实现多数据源JTA分布式事务
JTA集成JOTM或Atomikos配置分布式事务(Tomcat应用服务器)
Spring + Atomikos 分布式事务实现方式
Java学习路线分享MyBatis之Spring整合
sqlserver的相关东西
在spring中使用声明型事务
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服