• spring+jotm+ibatis+mysql实现JTA分布式事务


    1 环境

    1.1 软件环境

     spring-framework-2.5.6.SEC01-with-dependencies.zip
     ibatis-2.3.4
     ow2-jotm-dist-2.1.4-bin.tar.gz
     MySQL-5.1
     JDK1.5
     
    1.2 创建数据库环境
    注意mysql里数据库引擎为InnoDB,只有这样才能支持事务
     1 CREATE DATABASE IF NOT EXISTS testdb_a    DEFAULT CHARACTER SET utf8; 
     2 
     3 USE testdb_a; 
     4 
     5 DROP TABLE IF EXISTS tab_a; 
     6 
     7 CREATE TABLE tab_a ( 
     8     id bigint(20) NOT NULL, 
     9     name varchar(60) DEFAULT NULL, 
    10     address varchar(120) DEFAULT NULL, 
    11     PRIMARY KEY (id) 
    12 ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 
    13 
    14 
    15 CREATE DATABASE IF NOT EXISTS testdb_b    DEFAULT CHARACTER SET utf8; 
    16 
    17 USE testdb_b; 
    18 
    19 DROP TABLE IF EXISTS tab_b; 
    20 
    21 CREATE TABLE tab_b ( 
    22     id bigint(20) NOT NULL, 
    23     name varchar(60) DEFAULT NULL, 
    24     address varchar(120) DEFAULT NULL, 
    25     PRIMARY KEY (id) 
    26 ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 
    View Code

    建立项目testJOTM

    2.1 建立项目后,准备依赖的类库,结构如下

    2.2 主要代码

     1 /**
     2  * 测试JOTM的Service
     3  *
     4  * @author leizhimin 2009-6-25 12:53:55
     5  */
     6 public interface StuJotmService {
     7     /**
     8      * 同时保存TabA、TabB
     9      *
    10      * @param a
    11      *            TabA对象
    12      * @param b
    13      *            TabB对象
    14      */
    15     void saveAB(TabA a, TabB b);
    16 
    17     /**
    18      * 同时更新TabA、TabB
    19      *
    20      * @param a
    21      *            TabA对象
    22      * @param b
    23      *            TabB对象
    24      */
    25     void updateAB(TabA a, TabB b);
    26 
    27     /**
    28      * 删除指定id的TabA、TabB记录
    29      *
    30      * @param id
    31      *            指定id
    32      */
    33     void deleteABif(Long id);
    34 }
    StuJotmService
     1 public class StuJotmServiceImpl implements StuJotmService {
     2     private TabADAO tabADAO;
     3     private TabBDAO tabBDAO;
     4 
     5     /**
     6      * 同时保存TabA、TabB
     7      *
     8      * @param a
     9      *            TabA对象
    10      * @param b
    11      *            TabB对象
    12      */
    13 //    @Transactional(readOnly=false)
    14     public void saveAB(TabA a, TabB b) {
    15         tabADAO.saveTabA(a);
    16         tabBDAO.saveTabB(b);
    17     }
    18 
    19     /**
    20      * 同时更新TabA、TabB
    21      *
    22      * @param a
    23      *            TabA对象
    24      * @param b
    25      *            TabB对象
    26      */
    27     // @Transactional(readOnly=false)
    28     public void updateAB(TabA a, TabB b) {
    29         tabADAO.updateTabA(a);
    30         tabBDAO.updateTabB(b);
    31     }
    32 
    33     /**
    34      * 删除指定id的TabA、TabB记录
    35      *
    36      * @param id
    37      *            指定id
    38      */
    39     // @Transactional(readOnly=false)
    40     public void deleteABif(Long id) {
    41         tabADAO.deleteTabAById(id);
    42         tabBDAO.deleteTabBById(id);
    43     }
    44 
    45     public void setTabADAO(TabADAO tabADAO) {
    46         this.tabADAO = tabADAO;
    47     }
    48 
    49     public void setTabBDAO(TabBDAO tabBDAO) {
    50         this.tabBDAO = tabBDAO;
    51     }
    52 }
    StuJotmServiceImpl
      1 <?xml version="1.0" encoding="UTF-8"?>
      2 <!-- 局部单元测试使用,不正式发布,不要删除 -->
      3 <beans xmlns="http://www.springframework.org/schema/beans"
      4     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee"
      5     xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
      6     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
      7                      http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.0.xsd
      8                      http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
      9                      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
     10 
     11     <!--指定Spring配置中用到的属性文件 -->
     12     <bean id="propertyConfig"
     13         class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
     14         <property name="locations">
     15             <list>
     16                 <value>classpath:jdbc.properties</value>
     17             </list>
     18         </property>
     19     </bean>
     20     <!-- JOTM实例 -->
     21     <bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean" />
     22     <!-- JTA事务管理器 -->
     23     <bean id="myJtaManager"
     24         class="org.springframework.transaction.jta.JtaTransactionManager">
     25         <property name="userTransaction">
     26             <ref local="jotm" />
     27         </property>
     28     </bean>
     29     <!-- 数据源A -->
     30     <bean id="dataSourceA" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource"
     31         destroy-method="shutdown">
     32         <property name="dataSource">
     33             <bean class="org.enhydra.jdbc.standard.StandardXADataSource"
     34                 destroy-method="shutdown">
     35                 <property name="transactionManager" ref="jotm" />
     36                 <property name="driverName" value="${jdbc.driver}" />
     37                 <property name="url" value="${jdbc.url}" />
     38             </bean>
     39         </property>
     40         <property name="user" value="${jdbc.username}" />
     41         <property name="password" value="${jdbc.password}" />
     42     </bean>
     43     <!-- 数据源B -->
     44     <bean id="dataSourceB" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource"
     45         destroy-method="shutdown">
     46         <property name="dataSource">
     47             <bean class="org.enhydra.jdbc.standard.StandardXADataSource"
     48                 destroy-method="shutdown">
     49                 <property name="transactionManager" ref="jotm" />
     50                 <property name="driverName" value="${jdbc2.driver}" />
     51                 <property name="url" value="${jdbc2.url}" />
     52             </bean>
     53         </property>
     54         <property name="user" value="${jdbc2.username}" />
     55         <property name="password" value="${jdbc.password}" />
     56     </bean>
     57     <!-- 事务切面配置 -->
     58     <aop:config>
     59         <aop:pointcut id="serviceOperation" expression="execution(* *..service*..*(..))" />
     60         <aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice" />
     61     </aop:config>
     62     <!-- 通知配置 -->
     63     <tx:advice id="txAdvice" transaction-manager="myJtaManager">
     64         <tx:attributes>
     65             <tx:method name="delete*" rollback-for="Exception" />
     66             <tx:method name="save*" rollback-for="Exception" />
     67             <tx:method name="update*" rollback-for="Exception" />
     68             <tx:method name="*" read-only="true" rollback-for="Exception" />
     69         </tx:attributes>
     70     </tx:advice>
     71 
     72     <!--根据dataSourceA和sql-map-config_A.xml创建一个SqlMapClientA -->
     73     <bean id="sqlMapClientA" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
     74         <property name="dataSource">
     75             <ref local="dataSourceA" />
     76         </property>
     77         <property name="configLocation">
     78             <value>sql-map-config_A.xml</value>
     79         </property>
     80     </bean>
     81     <!--根据dataSourceB和sql-map-config_B.xml创建一个SqlMapClientB -->
     82     <bean id="sqlMapClientB" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
     83         <property name="dataSource">
     84             <ref local="dataSourceB" />
     85         </property>
     86         <property name="configLocation">
     87             <value>sql-map-config_B.xml</value>
     88         </property>
     89     </bean>
     90     <!--根据sqlMapClientA创建一个SqlMapClientTemplate的模版类实例sqlMapClientTemplateA -->
     91     <bean id="sqlMapClientTemplateA" class="org.springframework.orm.ibatis.SqlMapClientTemplate">
     92         <property name="sqlMapClient" ref="sqlMapClientA" />
     93     </bean>
     94     <!--根据sqlMapClientB创建一个SqlMapClientTemplate的模版类实例sqlMapClientTemplateB -->
     95     <bean id="sqlMapClientTemplateB" class="org.springframework.orm.ibatis.SqlMapClientTemplate">
     96         <property name="sqlMapClient" ref="sqlMapClientB" />
     97     </bean>
     98 
     99     <!-- 配置DAO,并注入所使用的sqlMapClientTemplate实例 -->
    100     <bean id="tabADAO" class="com.lavasoft.stu.jtom.dao.impl.TabADAOImpl">
    101         <property name="sqlMapClientTemplate" ref="sqlMapClientTemplateA" />
    102     </bean>
    103     <bean id="tabBDAO" class="com.lavasoft.stu.jtom.dao.impl.TabBDAOImpl">
    104         <property name="sqlMapClientTemplate" ref="sqlMapClientTemplateB" />
    105     </bean>
    106 
    107     <!-- Service配置,注入DAO -->
    108     <bean id="stuJotmService" class="com.lavasoft.stu.jtom.service.StuJotmServiceImpl">
    109         <property name="tabADAO" ref="tabADAO" />
    110         <property name="tabBDAO" ref="tabBDAO" />
    111     </bean>
    112 </beans>
    applicationContext.xml
     1 jdbc.database=cms_release
     2 jdbc.driver=com.mysql.jdbc.Driver
     3 jdbc.url=jdbc:mysql://192.168.0.1:3306/test?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull
     4 jdbc.username=root
     5 jdbc.password=123456
     6 
     7 jdbc2.database=cms_release
     8 jdbc2.driver=com.mysql.jdbc.Driver
     9 jdbc2.url=jdbc:mysql://192.168.0.2:3306/test?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull
    10 jdbc2.username=root
    11 jdbc2.password=123456
    jdbc.properties
     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <!DOCTYPE sqlMapConfig
     3                 PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
     4                 "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
     5 
     6 <sqlMapConfig>
     7         <settings cacheModelsEnabled="true" enhancementEnabled="true"
     8                             lazyLoadingEnabled="true" errorTracingEnabled="true"
     9                             useStatementNamespaces="true"/>
    10 
    11         <sqlMap resource="com/lavasoft/stu/jtom/entity/sqlmap/TabA.xml"/>
    12 
    13 </sqlMapConfig>
    sql-map-config_A.xml
     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <!DOCTYPE sqlMapConfig
     3                 PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
     4                 "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
     5 
     6 <sqlMapConfig>
     7         <settings cacheModelsEnabled="true" enhancementEnabled="true"
     8                             lazyLoadingEnabled="true" errorTracingEnabled="true"
     9                             useStatementNamespaces="true"/>
    10 
    11         <sqlMap resource="com/lavasoft/stu/jtom/entity/sqlmap/TabB.xml"/>
    12 
    13 </sqlMapConfig>
    sql-map-config_B.xml
     1 public class Test {
     2     private static ApplicationContext ctx = ApplicationContextUtil.getApplicationContext();
     3     private static StuJotmService ser = (StuJotmService) ctx.getBean("stuJotmService");
     4 
     5     public static void test_() {
     6         TabA a = new TabA();
     7         a.setId(2L);
     8         a.setName("aaa4");
     9         a.setAddress("address a4");
    10 
    11         TabB b = new TabB();
    12         b.setId(3L);
    13         b.setName("bbb3");
    14         b.setAddress("address b5");
    15         
    16         ser.saveAB(a, b);
    17     }
    18 
    19     public static void main(String[] args) {
    20         test_();
    21     }
    22 }

    2.3 测试效果

    先运行Test文件,可以看到两个库两个表都正常插入值。

     

    再把TabA的setId改为其他任意一个长整型,那么TabB肯定会报主键重复错,因为TabB的setId没改,那么如果事务生效的话,最后应该是两张表都没插入值,如果事务没生效,那么TabA会插入一条新的数据。

     

     2.3 完整结构

     完整代码下载:

  • 相关阅读:
    0107. Binary Tree Level Order Traversal II (E)
    0052. N-Queens II (H)
    0051. N-Queens (H)
    0441. Arranging Coins (E)
    面向对象的三大特性
    Java面向对象
    Java方法
    Java流程控制
    Scanner 类
    Java基础语法
  • 原文地址:https://www.cnblogs.com/shamo89/p/7307961.html
Copyright © 2020-2023  润新知