tomcat + jta + spring (3)

最近因为业务需要,因为客票系统的数据量非常之大,需要对数据进行分散部署,而且数据库分布在不同城市,对于单数据库的操作来说事物很简单就可以处理好,但是对于多数据库来说,如何保持数据的一致性,则需要分布式事物处理。


所谓分布式事务,就是数据源不止一个,可能有两个或更多,在一些大型应用中常常出现,常用的解决办法就是使用JTA,但是如果使用tomcat(用其他容器也一样可以使用此方式操作,当然直接使用容器支持的分布式事物是最好的,如jboss或其他的web容器)作为容器则它本身不支持JTA事物,所以需要用到第三方库,此例中使用Atomikosessential库(具体信息可以通过搜索得到,多动手吧!)。


本例环境(本例只模拟两个数据库的情况,多个数据库就多写几个数据源即可,在此不多复述了)


数据库:数据库1(广州mysql,地址是10.108.1.14);数据库2(上海oracle,地址是10.10.128.126),两个数据库分别部署在网络上的不同地址;


测试内容:同时往两个数据库添加一条数据,分别测试合法数据和不合法数据的情况,如果合法应该同时提交事务,不合法的则会回滚事务
使用的技术内容:大家常用的ssh(当然也可以不用这些,其他的技术内容完全可以,只是为了照顾大家的一个使用习惯)


演示内容
首先配置ssh
     hibernate的配置放到spring配置文件中,配置如下:
spring-ds.xml文件内容
[CODE]
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
 <bean id="webDs" class="com.atomikos.jdbc.AtomikosDataSourceBean"
  init-method="init" destroy-method="close">
  <property name="uniqueResourceName">
   <value>mysql/main</value>
  </property>
  <property name="xaDataSourceClassName">
   <value>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</value>
  </property>
  <property name="xaProperties">
   <props>
    <prop key="user">root</prop>
    <prop key="password"></prop>
    <prop key="URL">jdbc:mysql://127.0.0.1:3306/localmember?zeroDateTimeBehavior=convertToNull&amp;transformedBitIsBoolean=true&amp;autoReconnect=true&amp;useUnicode=true&amp;characterEncoding=UTF-8
    </prop>
   </props>
  </property>
  <property name="poolSize">
   <value>50</value>
  </property>
 </bean>
 
 <bean id="storeDs" class="com.atomikos.jdbc.AtomikosDataSourceBean"
  init-method="init" destroy-method="close">
  <property name="uniqueResourceName">
   <value>oracle/main</value>
  </property>
  <property name="xaDataSourceClassName">
   <value>oracle.jdbc.xa.client.OracleXADataSource</value>
  </property>
  <property name="xaProperties">
   <props>
    <prop key="user">dbusrcard</prop>
    <prop key="password">futurecard</prop>
    <prop key="URL">jdbc:oracle:thin:@localhost:1521:xe</prop>
   </props>
  </property>
  <property name="poolSize">
   <value>30</value>
  </property>
 </bean>
</beans>
[/CODE]
spring-dao.xml文件内容
 [CODE]
<?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:aop="http://www.springframework.org/schema/aop"
 xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
 xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
 <bean id="storeSessionFactory"
  class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  <property name="dataSource" ref="storeDs" />
  <property name="mappingResources">
   <list>
    <value>net/hlin/multitx/entity/StoreTestTb.hbm.xml</value>
   </list>
  </property>
  <property name="hibernateProperties">
   <value>
    hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
    hibernate.show_sql=true
    hibernate.format_sql=true
   </value>
  </property>
 </bean>
 <bean id="webSessionFactory"
  class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  <property name="dataSource" ref="webDs" />
  <property name="mappingResources">
   <list>
    <value>net/hlin/multitx/entity/WebTestTb.hbm.xml</value>
   </list>
  </property>
  <property name="hibernateProperties">
   <value>
    hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
    hibernate.show_sql=true
    hibernate.format_sql=true
   </value>
  </property>
 </bean>
 <bean id="webDao" class="net.hlin.multitx.dao.WebDao">
  <property name="sessionFactory" ref="webSessionFactory" />
 </bean>
 <bean id="storeDao" class="net.hlin.multitx.dao.StoreDao">
  <property name="sessionFactory" ref="storeSessionFactory" />
 </bean>
 <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp" />
 <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
  init-method="init" destroy-method="close">
  <property name="forceShutdown">
   <value>true</value>
  </property>
 </bean>
 <bean id="txManager"
  class="org.springframework.transaction.jta.JtaTransactionManager">
  <property name="transactionManager">
   <ref bean="atomikosTransactionManager" />
  </property>
  <property name="userTransaction">
   <ref bean="atomikosUserTransaction" />
  </property>
 </bean>
 <tx:advice id="txAdvice" transaction-manager="txManager">
  <tx:attributes>
   <tx:method name="add*" propagation="REQUIRED" rollback-for="java.lang.Exception" />
  </tx:attributes>
 </tx:advice>
 <aop:config>
  <aop:advisor advice-ref="txAdvice"
   pointcut="execution(* net.hlin.multitx.service.*.*(..))" />
 </aop:config>
<!--因为业务代码配置只有2行,所以直接写在这里了,正式开发环境中请遵守开发规范-->
 <context:annotation-config />
 <context:component-scan base-package="net.hlin.multitx.service" />
</beans>
[/CODE]


hbm文件省略,按各自爱好写即可
业务逻辑类TestService.java(名字不怎么规范,自己换吧!)
[CODE]
package net.hlin.multitx.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import net.hlin.multitx.dao.StoreDao;
import net.hlin.multitx.dao.WebDao;
import net.hlin.multitx.entity.TestTb;
@Component
public class TestService {
 
 @Autowired
 private WebDao webDao;
 @Autowired
 private StoreDao storeDao;
 
 public void testMethod() {
  //测试成功的
  webDao.add(new TestTb(100, "a"));
  storeDao.add(new TestTb(102, "b"));
  /*第一次测试完成后接着把这段解注释,再次运行业务类这次因为有一次数据重复,数据要回滚
   webDao.add(new TestTb(101, "a"));
  storeDao.add(new TestTb(102, "b"));
   */
 }
 
 public void setWebDao(WebDao webDao) {
  this.webDao = webDao;
 }
 public void setStoreDao(StoreDao storeDao) {
  this.storeDao = storeDao;
 }
}
[/CODE]
最终的测试类 TestServiceTest .java
[CODE]
package net.hlin.multitx.service;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:spring-ds.xml", "classpath:spring-dao.xml"})
public class TestServiceTest {


@Autowired
private TestService testService;
@Test
public void testTestMethod() {
testService.testMethod();
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值