聊天网站站怎么做,做网站需要买域名,wordpress 分类文章置顶,长沙制作公园仿竹围栏供货商在本系列先前的文章中#xff0c;我们主要讲解了JDBC对本地事务的处理#xff0c;本篇文章将讲到一个分布式事务的例子。请通过以下方式下载github源代码#xff1a;本地事务和分布式事务的区别在于#xff1a;本地事务只用于处理单一数据源事务(比如单个数据库)#xff0…在本系列先前的文章中我们主要讲解了JDBC对本地事务的处理本篇文章将讲到一个分布式事务的例子。请通过以下方式下载github源代码本地事务和分布式事务的区别在于本地事务只用于处理单一数据源事务(比如单个数据库)分布式事务可以处理多种异构的数据源比如某个业务操作中同时包含了JDBC和JMS或者某个操作需要访问多个不同的数据库。Java通过JTA完成分布式事务JTA本身只是一种规范不同的应用服务器都包含有自己的实现(比如JbossJTA)同时还存在独立于应用服务器的单独JTA实现比如本篇中要讲到的Atomikos。对于JTA的原理这里不细讲读者可以通过这篇文章了解相关知识。在本篇文章中我们将实现以下一个应用场景你在网上购物下了订单之后订单数据将保存在系统的数据库中同时为了安排物流订单信息将以消息(Message)的方式发送到物流部门以便送货。以上操作同时设计到数据库操作和JMS消息发送为了使整个操作成为一个原子操作我们只能选择分布式事务。我们首先设计一个service层定义OrderService接口packagedavenkin;public interfaceOrderService {public voidmakeOrder(Order order);}为了简单起见我们设计一个非常简单的领域对象OrderXmlRootElement(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;OverrideTransactionalpublic voidmakeOrder(Order order) {Session sessionsessionFactory.getCurrentSession();session.save(order);jmsTemplate.convertAndSend(order);}Requiredpublic voidsetJmsTemplate(JmsTemplate jmsTemplate) {this.jmsTemplate jmsTemplate;}Requiredpublic voidsetSessionFactory(SessionFactory sessionFactory) {this.sessionFactory sessionFactory;}}(四)创建Order的Mapping配置文件/phttp://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd(五)配置Atomikos事务在Spring的IoC容器中我们需要配置由Atomikos提供的UserTransaction和TransactionManager然后再配置Spring的JtaTransactionManagercom.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());}