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,只有这样才能支持事务。
 CREATE DATABASE IF NOT EXISTS testdb_a    DEFAULT CHARACTER SET utf8; 

 USE testdb_a; 

 DROP TABLE IF EXISTS tab_a; 

 CREATE TABLE tab_a (
id bigint(20) NOT NULL,
name varchar(60) DEFAULT NULL,
address varchar(120) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE DATABASE IF NOT EXISTS testdb_b DEFAULT CHARACTER SET utf8; USE testdb_b; DROP TABLE IF EXISTS tab_b; CREATE TABLE tab_b (
id bigint(20) NOT NULL,
name varchar(60) DEFAULT NULL,
address varchar(120) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

建立项目testJOTM

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

2.2 主要代码

 /**
* 测试JOTM的Service
*
* @author leizhimin 2009-6-25 12:53:55
*/
public interface StuJotmService {
/**
* 同时保存TabA、TabB
*
* @param a
* TabA对象
* @param b
* TabB对象
*/
void saveAB(TabA a, TabB b); /**
* 同时更新TabA、TabB
*
* @param a
* TabA对象
* @param b
* TabB对象
*/
void updateAB(TabA a, TabB b); /**
* 删除指定id的TabA、TabB记录
*
* @param id
* 指定id
*/
void deleteABif(Long id);
}

StuJotmService

 public class StuJotmServiceImpl implements StuJotmService {
private TabADAO tabADAO;
private TabBDAO tabBDAO; /**
* 同时保存TabA、TabB
*
* @param a
* TabA对象
* @param b
* TabB对象
*/
// @Transactional(readOnly=false)
public void saveAB(TabA a, TabB b) {
tabADAO.saveTabA(a);
tabBDAO.saveTabB(b);
} /**
* 同时更新TabA、TabB
*
* @param a
* TabA对象
* @param b
* TabB对象
*/
// @Transactional(readOnly=false)
public void updateAB(TabA a, TabB b) {
tabADAO.updateTabA(a);
tabBDAO.updateTabB(b);
} /**
* 删除指定id的TabA、TabB记录
*
* @param id
* 指定id
*/
// @Transactional(readOnly=false)
public void deleteABif(Long id) {
tabADAO.deleteTabAById(id);
tabBDAO.deleteTabBById(id);
} public void setTabADAO(TabADAO tabADAO) {
this.tabADAO = tabADAO;
} public void setTabBDAO(TabBDAO tabBDAO) {
this.tabBDAO = tabBDAO;
}
}

StuJotmServiceImpl

 <?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:jee="http://www.springframework.org/schema/jee"
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/jee http://www.springframework.org/schema/jee/spring-jee-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"> <!--指定Spring配置中用到的属性文件 -->
<bean id="propertyConfig"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
</list>
</property>
</bean>
<!-- JOTM实例 -->
<bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean" />
<!-- JTA事务管理器 -->
<bean id="myJtaManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="userTransaction">
<ref local="jotm" />
</property>
</bean>
<!-- 数据源A -->
<bean id="dataSourceA" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource"
destroy-method="shutdown">
<property name="dataSource">
<bean class="org.enhydra.jdbc.standard.StandardXADataSource"
destroy-method="shutdown">
<property name="transactionManager" ref="jotm" />
<property name="driverName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
</bean>
</property>
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!-- 数据源B -->
<bean id="dataSourceB" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource"
destroy-method="shutdown">
<property name="dataSource">
<bean class="org.enhydra.jdbc.standard.StandardXADataSource"
destroy-method="shutdown">
<property name="transactionManager" ref="jotm" />
<property name="driverName" value="${jdbc2.driver}" />
<property name="url" value="${jdbc2.url}" />
</bean>
</property>
<property name="user" value="${jdbc2.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!-- 事务切面配置 -->
<aop:config>
<aop:pointcut id="serviceOperation" expression="execution(* *..service*..*(..))" />
<aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice" />
</aop:config>
<!-- 通知配置 -->
<tx:advice id="txAdvice" transaction-manager="myJtaManager">
<tx:attributes>
<tx:method name="delete*" rollback-for="Exception" />
<tx:method name="save*" rollback-for="Exception" />
<tx:method name="update*" rollback-for="Exception" />
<tx:method name="*" read-only="true" rollback-for="Exception" />
</tx:attributes>
</tx:advice> <!--根据dataSourceA和sql-map-config_A.xml创建一个SqlMapClientA -->
<bean id="sqlMapClientA" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="dataSource">
<ref local="dataSourceA" />
</property>
<property name="configLocation">
<value>sql-map-config_A.xml</value>
</property>
</bean>
<!--根据dataSourceB和sql-map-config_B.xml创建一个SqlMapClientB -->
<bean id="sqlMapClientB" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="dataSource">
<ref local="dataSourceB" />
</property>
<property name="configLocation">
<value>sql-map-config_B.xml</value>
</property>
</bean>
<!--根据sqlMapClientA创建一个SqlMapClientTemplate的模版类实例sqlMapClientTemplateA -->
<bean id="sqlMapClientTemplateA" class="org.springframework.orm.ibatis.SqlMapClientTemplate">
<property name="sqlMapClient" ref="sqlMapClientA" />
</bean>
<!--根据sqlMapClientB创建一个SqlMapClientTemplate的模版类实例sqlMapClientTemplateB -->
<bean id="sqlMapClientTemplateB" class="org.springframework.orm.ibatis.SqlMapClientTemplate">
<property name="sqlMapClient" ref="sqlMapClientB" />
</bean> <!-- 配置DAO,并注入所使用的sqlMapClientTemplate实例 -->
<bean id="tabADAO" class="com.lavasoft.stu.jtom.dao.impl.TabADAOImpl">
<property name="sqlMapClientTemplate" ref="sqlMapClientTemplateA" />
</bean>
<bean id="tabBDAO" class="com.lavasoft.stu.jtom.dao.impl.TabBDAOImpl">
<property name="sqlMapClientTemplate" ref="sqlMapClientTemplateB" />
</bean> <!-- Service配置,注入DAO -->
<bean id="stuJotmService" class="com.lavasoft.stu.jtom.service.StuJotmServiceImpl">
<property name="tabADAO" ref="tabADAO" />
<property name="tabBDAO" ref="tabBDAO" />
</bean>
</beans>

applicationContext.xml

 jdbc.database=cms_release
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://192.168.0.1:3306/test?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull
jdbc.username=root
jdbc.password=123456 jdbc2.database=cms_release
jdbc2.driver=com.mysql.jdbc.Driver
jdbc2.url=jdbc:mysql://192.168.0.2:3306/test?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull
jdbc2.username=root
jdbc2.password=123456

jdbc.properties

 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMapConfig
PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-config-2.dtd"> <sqlMapConfig>
<settings cacheModelsEnabled="true" enhancementEnabled="true"
lazyLoadingEnabled="true" errorTracingEnabled="true"
useStatementNamespaces="true"/> <sqlMap resource="com/lavasoft/stu/jtom/entity/sqlmap/TabA.xml"/> </sqlMapConfig>

sql-map-config_A.xml

 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMapConfig
PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-config-2.dtd"> <sqlMapConfig>
<settings cacheModelsEnabled="true" enhancementEnabled="true"
lazyLoadingEnabled="true" errorTracingEnabled="true"
useStatementNamespaces="true"/> <sqlMap resource="com/lavasoft/stu/jtom/entity/sqlmap/TabB.xml"/> </sqlMapConfig>

sql-map-config_B.xml

 public class Test {
private static ApplicationContext ctx = ApplicationContextUtil.getApplicationContext();
private static StuJotmService ser = (StuJotmService) ctx.getBean("stuJotmService"); public static void test_() {
TabA a = new TabA();
a.setId(2L);
a.setName("aaa4");
a.setAddress("address a4"); TabB b = new TabB();
b.setId(3L);
b.setName("bbb3");
b.setAddress("address b5"); ser.saveAB(a, b);
} public static void main(String[] args) {
test_();
}
}

2.3 测试效果

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

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

2.3 完整结构

完整代码下载:

spring+jotm+ibatis+mysql实现JTA分布式事务的更多相关文章

  1. Springboot+Atomikos+Jpa+Mysql实现JTA分布式事务

    1 前言 之前整理了一个spring+jotm实现的分布式事务实现,但是听说spring3.X后不再支持jotm了,jotm也有好几年没更新了,所以今天整理springboot+Atomikos+jp ...

  2. Spring 3.0 + Atomikos构建jta分布式事务

    Spring3.0已经不再支持jtom了,不过我们可以用第三方开源软件atomikos(http://www.atomikos.com/)来实现.Atomikos是目前在分布式事务管理中做得相当不错的 ...

  3. Springboot + Atomikos + Druid + Mysql 实现JTA分布式事务

    DataSource 配置 package com.cheng.dynamic.config; import java.util.Properties; import javax.sql.DataSo ...

  4. 使用Atomikos Transactions Essentials实现多数据源JTA分布式事务--转载

    原文:http://www.ite/topic/122700 9.17 update:使用NonXADataSourceBean. Mysql在5.0版本和Connecter/J5.0版本后提供了XA ...

  5. Spring Boot2.0之多数据源分布式事务问题

    分布式事务解决方案的问题, 分布式事务产生的原因: 多个不同的服务连接不同的数据源 ,做分布式事务的管理. 这种情况是连接两个数据源的情况,然后事务管理器是这样的 只管理了test02的这端业务代码. ...

  6. springboot学习笔记:10.springboot+atomikos+mysql+mybatis+druid+分布式事务

    前言 上一篇文章我们整合了springboot+druid+mybatis+mysql+多数据源: 本篇文章大家主要跟随你们涛兄在上一届基础上配置一下多数据源情况下的分布式事务: 首先,到底啥是分布式 ...

  7. spring boot:shardingsphere+druid整合seata分布式事务(spring boot 2.3.3)

    一,shardingshpere为什么要整合seata? 分库分表是数据库扩展中最常用的处理方法, shardingshpere作为使用最广泛的分表中间件, 如果不支持分布式事务,则它的数据一致性就会 ...

  8. Spring Cloud Alibaba 使用Seata解决分布式事务

    为什么会产生分布式事务? 随着业务的快速发展,网站系统往往由单体架构逐渐演变为分布式.微服务架构,而对于数据库则由单机数据库架构向分布式数据库架构转变.此时,我们会将一个大的应用系统拆分为多个可以独立 ...

  9. JTA 分布式事务

    什么是JTA - 2009-07-25 18:31:06|  分类: 技术文章|举报|字号 订阅     什么是JTA? Java Transaction API(Java事务API) (JTA)Ja ...

随机推荐

  1. STL - list(双向链表)

    List简介 list是一个双向链表容器,可高效地进行插入删除元素. list不可以随机存取元素,所以不支持at.(pos)函数与[]操作符.It++(ok) it+5(err) #include & ...

  2. Android Hal 分析

    本文是基于android4.0.3.对应其他低版本的代码,可能有所差异,但基本大同小异. Android的HAL是为了保护一些硬件提供商的知识产权而提出的,是为了避开linux的GPL束缚.思路是把控 ...

  3. 文档流 css中的float clear与布局

    文档流 先说说什么是文档流  流是什么 就是一串连续的东西 <div style="background-color:pink;width:40px;height:80px;" ...

  4. Android特效专辑(十一)——仿水波纹流量球进度条控制器,实现高端大气的主流特效

    Android特效专辑(十一)--仿水波纹流球进度条控制器,实现高端大气的主流特效 今天看到一个效果挺不错的,就模仿了下来,加上了一些自己想要的效果,感觉还不错的样子,所以就分享出来了,话不多说,上图 ...

  5. how tomcat works 总结

    希望各位网友在看完<<how tomcat works>>一书或者鄙人的tomcat专栏文章后再看这篇博客 这里主要是梳理各个章节的核心概念 第一章 一个简单的Web服务器 第 ...

  6. InvocationTargetException异常解析

    InvocationTargetException异常由Method.invoke(obj, args...)方法抛出.) { throw new ZeroException("参数不能小于 ...

  7. imooc网的主体框架

    imooc网的主体框架,主要是里面的导航动画做的比较好,大家可以学习下. git地址:https://github.com/xiangzhihong/ImoocPro

  8. miniui几个常用知识点汇总

    1.在表格中去除系统自带的序列号,请看代码: function allAndBrief(id) { if(id==1){ grid.set({ columns: [ { type: "ind ...

  9. Django(二)如何在IIS中部署django项目

    环境配置 windows7 Django 2.0 python 3.6 wfastcgi 3.0 关键步骤 打开CGI功能 控制面板/程序和功能/打开或关闭windwos功能,如图: 安装wfastc ...

  10. CSS的应用下

    样式继承: 就是父类的颜色如果变了,子类下的div(或者其他属性)会继承父类的. 参考代码: <!DOCTYPE html> <html lang="en"> ...