在本系列先前的文章中,我们主要讲解了JDBC对本地事务的处理,本篇文章将讲到一个分布式事务的例子。

请通过以下方式下载github源代码:

本地事务和分布式事务的区别在于:本地事务只用于处理单一数据源事务(比如单个数据库),分布式事务可以处理多种异构的数据源,比如某个业务操作中同时包含了JDBC和JMS或者某个操作需要访问多个不同的数据库。

Java通过JTA完成分布式事务,JTA本身只是一种规范,不同的应用服务器都包含有自己的实现(比如JbossJTA),同时还存在独立于应用服务器的单独JTA实现,比如本篇中要讲到的Atomikos。对于JTA的原理,这里不细讲,读者可以通过这篇文章了解相关知识。

在本篇文章中,我们将实现以下一个应用场景:你在网上购物,下了订单之后,订单数据将保存在系统的数据库中,同时为了安排物流,订单信息将以消息(Message)的方式发送到物流部门以便送货。

以上操作同时设计到数据库操作和JMS消息发送,为了使整个操作成为一个原子操作,我们只能选择分布式事务。我们首先设计一个service层,定义OrderService接口:

packagedavenkin;public interfaceOrderService {public voidmakeOrder(Order order);

}

为了简单起见,我们设计一个非常简单的领域对象Order:

@XmlRootElement(name = "Order")

@XmlAccessorType(XmlAccessType.FIELD)public classOrder {

@XmlElement(name= "Id",required = true)private longid;

@XmlElement(name= "ItemName",required = true)privateString itemName;

@XmlElement(name= "Price",required = true)private doubleprice;

@XmlElement(name= "BuyerName",required = true)privateString buyerName;

@XmlElement(name= "MailAddress",required = true)privateString mailAddress;publicOrder() {

}

为了采用JAXB对Order对象进行Marshal和Unmarshal,我们在Order类中加入了JAXB相关的Annotation。 我们将使用Hibernate来完成数据持久化,然后使用Spring提供的JmsTemplate将Order转成xml后以TextMessage的形式发送到物流部门的ORDER.QUEUE中。

(一)准备数据库

为了方便,我们将采用Spring提供的embedded数据库,默认情况下Spring采用HSQL作为后台数据库,虽然在本例中我们将采用HSQL的非XA的DataSource,但是通过Atomikos包装之后依然可以参与分布式事务。

SQL脚本包含在createDB.sql文件中:

CREATE TABLEUSER_ORDER(

IDINT NOT NULL,

ITEM_NAMEVARCHAR (100) NOT NULL UNIQUE,

PRICEDOUBLE NOT NULL,

BUYER_NAMECHAR (32) NOT NULL,

MAIL_ADDRESSVARCHAR(500) NOT NULL,PRIMARY KEY(ID)

);

在Spring中配置DataSource如下:

(二)启动ActiveMQ

我们将采用embedded的ActiveMQ,在测试之前启动ActiveMQ提供的BrokerService,在测试执行完之后关闭BrokerService。

@BeforeClasspublic static void startEmbeddedActiveMq() throwsException {

broker= newBrokerService();

broker.addConnector("tcp://localhost:61616");

broker.start();

}

@AfterClasspublic static void stopEmbeddedActiveMq() throwsException {

broker.stop();

}

(三)实现OrderService

创建一个DefaultOrderService,该类实现了OrderService接口,并维护一个JmsTemplate和一个Hibernate的SessionFactory实例变量,分别用于Message的发送和数据库处理。

packagedavenkin;importorg.hibernate.SessionFactory;importorg.hibernate.classic.Session;importorg.springframework.beans.factory.annotation.Required;importorg.springframework.jms.core.JmsTemplate;importorg.springframework.transaction.annotation.Transactional;public class DefaultOrderService implementsOrderService{privateJmsTemplate jmsTemplate;privateSessionFactory sessionFactory;

@Override

@Transactionalpublic voidmakeOrder(Order order) {

Session session=sessionFactory.getCurrentSession();

session.save(order);

jmsTemplate.convertAndSend(order);

}

@Requiredpublic voidsetJmsTemplate(JmsTemplate jmsTemplate) {this.jmsTemplate =jmsTemplate;

}

@Requiredpublic voidsetSessionFactory(SessionFactory sessionFactory) {this.sessionFactory =sessionFactory;

}

}

(四)创建Order的Mapping配置文件

/p>

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

(五)配置Atomikos事务

在Spring的IoC容器中,我们需要配置由Atomikos提供的UserTransaction和TransactionManager,然后再配置Spring的JtaTransactionManager:

com.atomikos.icatch.standalone.UserTransactionServiceFactory

(六)配置JMS

对于JMS,为了能使ActiveMQ加入到分布式事务中,我们需要配置ActiveMQXAConnectionFactory,而不是ActiveMQConnectionFactory,然后再配置JmsTemplate,此外还需要配置MessageConvertor在Order对象和XML之间互转。

(七)测试

在测试中,我们首先通过(二)中的方法启动ActiveMQ,再调用DefaultOrderService,最后对数据库和QUEUE进行验证:

@Testpublic voidmakeOrder(){

orderService.makeOrder(createOrder());

JdbcTemplate jdbcTemplate= newJdbcTemplate(dataSource);

assertEquals(1, jdbcTemplate.queryForInt("SELECT COUNT(*) FROM USER_ORDER"));

String dbItemName= jdbcTemplate.queryForObject("SELECT ITEM_NAME FROM USER_ORDER", String.class);

String messageItemName=((Order) jmsTemplate.receiveAndConvert()).getItemName();

assertEquals(dbItemName, messageItemName);

}

@Test(expected= IllegalArgumentException.class)public voidfailToMakeOrder()

{

orderService.makeOrder(null);

JdbcTemplate jdbcTemplate= newJdbcTemplate(dataSource);

assertEquals(0, jdbcTemplate.queryForInt("SELECT COUNT(*) FROM USER_ORDER"));

assertNull(jmsTemplate.receiveAndConvert());

}

java jta 例子_Java事务处理全解析(八)——分布式事务入门例子(Spring+JTA+Atomikos+Hibernate+JMS)...相关推荐

  1. 分布式事务操作之Spring+JTA

    什么是分布式事务?在网上找了一段比较容易理解的"定义". 分布式事务是指事务的参与者.支持事务的服务器.资源管理器以及事务管理器分别位于分布系统的不同节点之上,在两个或多个网络计算 ...

  2. java中使用事务案例_Java事务处理全解析(四)—— 成功的案例(自己实现一个线程安全的TransactionManager)...

    在本系列的上一篇文章中我们讲到,要实现在同一个事务中使用相同的Connection对象,我们可以通过传递Connection对象的方式达到共享的目的,但是这种做法是丑陋的.在本篇文章中,我们将引入另外 ...

  3. springmvc atomikos mysql数据源_Spring多数据源分布式事务管理/springmvc+spring+atomikos[jta]+druid+mybatis...

    项目进行读写分离及分库分表,在一个业务中,在一个事务中处理时候将切换多个数据源,需要保证同一事务多个数据源数据的一致性.此处使用atomikos来实现:最后附源码: 1:spring3.0之后不再支持 ...

  4. Java事务之八——分布式事务(Spring+JTA+Atomikos+Hibernate+JMS)

    在本系列先前的文章中,我们主要讲解了JDBC对本地事务的处理,本篇文章将讲到一个分布式事务的例子. 请通过以下方式下载github源代码: git clone https://github.com/d ...

  5. 【BAT 面试题宝库附详尽答案解析】分布式事务实现原理

    问题场景 什么是事务? 事务是数据库从一个稳定状态变迁到另一个稳定状态的保证,具备 ACID 这 4 个特性: 原子性(Atomicity):一个事务中的所有操作,要么全部完成,要么全部不完成,不会结 ...

  6. java项目的事务怎么处理_java实际项目中如何处理分布式事务的

    分布式事务的解决方案(介绍其中三种) 两阶段提交协议(2PC) 为解决分布式系统的数据一致性问题出现了两阶段提交协议(2 Phase Commitment Protocol),两阶段提交由协调者和参与 ...

  7. Java帝国之宫廷内斗2(分布式事务消息队列、事务表)

    原文地址:https://mp.weixin.qq.com/s/92SghOorf10dm3pM0DWzIg 1.前情提要 上回说到IO大臣一直被JDBC大臣打压, 为了搞掉JDBC大臣, 他忍辱负重 ...

  8. Java开发 - 不知道算不算详细的分布式事务详解

    前言 前日对JUC进行了一个深度总结,不过现在博主能记得的也不多了,只是这东西,不是看几遍写几遍就能完全记住的,功夫在平时,很多知识点都需要反复的看,不光要看,还要用,这样才能了解其原理,掌握其原理, ...

  9. Java事务处理全解析(二)——失败的案例

    在本系列的上一篇文章中,我们讲到了Java事务处理的基本问题,并且讲到了Service层和DAO层,在本篇文章中,我们将以BankService为例学习一个事务处理失败的案例. BankService ...

最新文章

  1. 自动类型转换和强制类型转换
  2. Docker镜像优化
  3. python绘制中国加油_软件开发|使用 Python 为你的油箱加油
  4. 衡阳市2017计算机考试,2017湖南衡阳中考各科目满分及分值公告
  5. 一般性网络错误 请检查网络文档_如何编写好的软件设计文档
  6. 什么是 bootstrap 中的 break point
  7. Shell中case判断结构的用法笔记
  8. 【1】SCN-Eureka服务注册中心
  9. 利用CodeBlocks创建C语言项目
  10. 基于动力学前馈加反馈线性化的机器人动力学控制实现
  11. DWM安装及简略配置教程
  12. Bloodsucker ZOJ - 3551
  13. 刻意练习+一万小时定律+异类
  14. 计算机考试用户没有注册类,电脑中出现没有注册类别的错误提示怎么解决
  15. 网咖虚拟服务器主机,为什么网吧的主机这么便宜??但是玩大型游戏又不卡
  16. 需求文档(PRD文档)应该怎么写?
  17. JAVA 序列化http://www.importnew.com/17964.html
  18. 故事,零落,,,,,
  19. skype android添加好友,Skype for android使用教程
  20. AI 工具 22个使用场景、500个通用提问技巧说明

热门文章

  1. 解决window的bat脚本执行出现中文乱码的问题
  2. RabbitMQ 下载安装配置_集群高可用篇_02
  3. fatal: remote origin already exists.报错已成功解决
  4. 来来来!一次搞定各种数据库 SQL 执行计划:MySQL、Oracle
  5. 使用apache POI把list集合里面的实体写入Excel(java)
  6. Error和Exception(异常)
  7. html边框大一点,CSS3 框大小(box-sizing)
  8. java并发访问_Java并发访问
  9. C语言 函数缺省参数 - C语言零基础入门教程
  10. mysql到mysqli转变表_利用mysql和mysqli取得mysql的所有数据库和库中的所有表