美文网首页
分布式事务spring+JTA

分布式事务spring+JTA

作者: 会飞的蜗牛F | 来源:发表于2020-08-15 17:09 被阅读0次

1、jdbc操作分布式事务

分布式事务是指事务的参与者、支持事务的服务器、资源管理器以及事务管理器分别位于分布系统的不同节点之上,在两个或多个网络计算机资源上访问并且更新数据,将两个或多个网络计算机的数据进行的多次操作作为一个整体进行处理。如不同银行账户之间的转账。

对于在项目中接触到JTA,大部分的原因是因为在项目中需要操作多个数据库,同时,可以保证操作的原子性,保证对多个数据库的操作一致性。

在正式的项目中应该用springMVC(struts)+spring+hibernate(jpa)+jta,目前,先用spring+jta来完成基本的测试框架。下面我们看看代码

applicationContext-jta.xml


<pre style="margin: 0px; padding: 0px; overflow-wrap: break-word; font-family: &quot;Courier New&quot; !important; font-size: 12px !important;"> 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
 4     xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
 5     xsi:schemaLocation="http://www.springframework.org/schema/beans
 6            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
 7            http://www.springframework.org/schema/context
 8            http://www.springframework.org/schema/context/spring-context-2.5.xsd
 9 http://www.springframework.org/schema/aop 10 http://www.springframework.org/schema/aop/spring-aop-2.5.xsd 11 http://www.springframework.org/schema/tx 12            http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
13 
14     <!-- jotm 本地实例 -->
15     <bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean" />
16 
17 
18     <!-- JTA事务管理器 -->
19     <bean id="txManager"
20         class="org.springframework.transaction.jta.JtaTransactionManager">
21         <property name="userTransaction" ref="jotm"></property>
22     </bean>
23 
24     <!-- XAPool配置,内部包含了一个XA数据源,对应sshdb数据库 -->
25     <bean id="db1" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource"
26         destroy-method="shutdown">
27         <property name="dataSource">
28             <!-- 内部XA数据源 -->
29             <bean class="org.enhydra.jdbc.standard.StandardXADataSource"
30                 destroy-method="shutdown">
31                 <property name="transactionManager" ref="jotm" />
32                 <property name="driverName" value="com.mysql.jdbc.Driver" />
33                 <property name="url"
34                     value="jdbc:mysql://192.168.1.28:3306/sshdb?useUnicode=true&amp;characterEncoding=UTF-8" />
35             </bean>
36         </property>
37         <property name="user" value="root" />
38         <property name="password" value="123456" />
39     </bean>
40 
41     <!-- 另一个XAPool配置,内部包含另一个XA数据源,对应babasport数据库 -->
42     <bean id="db2" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource"
43         destroy-method="shutdown">
44         <property name="dataSource">
45             <bean class="org.enhydra.jdbc.standard.StandardXADataSource"
46                 destroy-method="shutdown">
47                 <property name="transactionManager" ref="jotm" />
48                 <property name="driverName" value="com.mysql.jdbc.Driver" />
49                 <property name="url"
50                     value="jdbc:mysql://192.168.1.28:3306/babasport?useUnicode=true&amp;characterEncoding=UTF-8" />
51             </bean>
52         </property>
53         <property name="user" value="root" />
54         <property name="password" value="123456" />
55     </bean>
56 
57     <!-- 配置访问sshdb数据源的Spring JDBC模板 -->
58     <bean id="sshdbTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
59         <property name="dataSource" ref="db1"></property>
60     </bean>
61 
62     <!-- 配置访问babasport数据源的Spring JDBC模板 -->
63     <bean id="babasportTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
64         <property name="dataSource" ref="db2"></property>
65     </bean>
66 </beans></pre>

小注一下:spring-tx-3.2.4.jar里面竟然没有org.springframework.transaction.jta.JotmFactoryBean类,如果你可以选择spring-tx-2.5.6.jar,或者自己建立一下这个类。

接下来,看下dao层测试的代码

1     @Resource(name = "txManager")
 2     private JtaTransactionManager txManager;
 9
10     protected JdbcTemplate babasport_jdbcTemplate;
11
12     /**
13      * sshdb sql jdbcTemplate
14      */
15     protected JdbcTemplate ssh_jdbcTemplate;
16
17     /**
18      * babasport sql jdbcTemplate
19      *
20      * @return
21      */
22     public JdbcTemplate getBabasport_jdbcTemplate() {
23         return babasport_jdbcTemplate;
24     }
25
26     public JdbcTemplate getSsh_jdbcTemplate() {
27         return ssh_jdbcTemplate;
28     }
29
30     @Resource(name = "babasportTemplate")
31     public void setBabasport_jdbcTemplate(JdbcTemplate babasport_jdbcTemplate) {
32         this.babasport_jdbcTemplate = babasport_jdbcTemplate;
33     }
34
35     @Resource(name = "sshdbTemplate")
36     public void setSsh_jdbcTemplate(JdbcTemplate ssh_jdbcTemplate) {
37         this.ssh_jdbcTemplate = ssh_jdbcTemplate;
38     }
39
40     /**
41      * 同时修改两个数据库的表中内容
42      *
43      * @throws RollbackException
44      */
45     public void updateMultiple() {
46
47         if (null == this.txManager) {
48             System.out.println("txManager为空");
49             return;
50         }
51
52         UserTransaction userTx = this.txManager.getUserTransaction();
53         if (null == userTx) {
54             System.out.println("userTx为空");
55             return;
56         }
57
58         try {
59
60             userTx.begin();
61
62             this.ssh_jdbcTemplate
63                     .execute("update wyuser set password='wangyong1' where id=8");
64
65
66             this.babasport_jdbcTemplate
67                     .execute("update brand set name='wangyong28' where code='14ac8d5b-d19c-40e9-97ea-d82dfbcd84c6'");
68
69             userTx.commit();
70         } catch (Exception e) {
71             System.out.println("捕获到异常,进行回滚" + e.getMessage());
72             e.printStackTrace();
73             try {
74                 userTx.rollback();
75             } catch (IllegalStateException e1) {
76                 System.out.println("IllegalStateException:" + e1.getMessage());
77             } catch (SecurityException e1) {
78                 System.out.println("SecurityException:" + e1.getMessage());
79             } catch (SystemException e1) {
80                 System.out.println("SystemException:" + e1.getMessage());
81             }
82             // System.out.println("sql语句操作失败");
83         }
84     }

如果,将后一条update语句故意写错,就会发现会执行rollback,同时,对上面一个语句的操作也不会生效。基本的简单框架就是这样。

2、spring+mybatis

1、数据源

#car数据源
spring.datasource.car.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.car.driverClassName=com.mysql.jdbc.Driver
spring.datasource.car.url=jdbc:mysql://ip:3306/db_car?useUnicode=true&characterEncoding=utf8&useSSL=false
spring.datasource.car.username=root
spring.datasource.car.password=123456
spring.datasource.car.initialSize=5
spring.datasource.car.minIdle=5
spring.datasource.car.maxActive=20
spring.datasource.car.maxWait=60000

# test 数据源
spring.datasource.test.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.test.driverClassName=com.mysql.jdbc.Driver
spring.datasource.test.url=jdbc:mysql://ip:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false
spring.datasource.test.username=root
spring.datasource.test.password=123456
spring.datasource.test.initialSize=5
spring.datasource.test.minIdle=5
spring.datasource.test.maxActive=20
spring.datasource.test.maxWait=60000

2、多数据源配置
这里只配置 car数据源的,test数据源的和这个一样,复制一份。

/**
 * Created by Administrator on 2017/3/26/026.
 * 数据源配置
 */
@Configuration
@MapperScan(basePackages = {"com.xxx.mapper.car*"}, sqlSessionTemplateRef = "sqlSessionTemplateCar") // 扫描dao或mapper接口
public class DataSourceCarConfig {

    @Primary
    @Bean(name = "dataSourceCar")
    public DataSource dataSourceCar(DataSourceCarProperties dataSourceCarProperties){
        DruidXADataSource dataSource = new DruidXADataSource();
        BeanUtils.copyProperties(dataSourceCarProperties,dataSource);
        AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
        xaDataSource.setXaDataSource(dataSource);
        xaDataSource.setUniqueResourceName("dataSourceCar");
        return xaDataSource;
    }


    @Bean(name = "sqlSessionFactoryCar")
    public SqlSessionFactory sqlSessionFactoryCar(@Qualifier("dataSourceCar") DataSource dataSource)
            throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setTypeAliasesPackage("com.lcj.web.entity.car");
        //bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:/mapper/car/*Mapper.xml"));
        return bean.getObject();
    }

    @Bean(name = "sqlSessionTemplateCar")
    public SqlSessionTemplate sqlSessionTemplateCar(
            @Qualifier("sqlSessionFactoryCar") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

@Component //自动注入
@ConfigurationProperties(prefix = "spring.datasource.car")
@Data
public class DataSourceCarProperties {
    private String type;
    private String driverClassName;
    private String url;
    private String username;
    private String password;
    private int initialSize;
    private int minIdle;
    private int maxActive;
    private int maxWait;
    private int timeBetweenEvictionRunsMillis;
    private int minEvictableIdleTimeMillis;
    private String validationQuery;
    private boolean testWhileIdle;
    private boolean testOnBorrow;
    private boolean testOnReturn;
    private boolean poolPreparedStatements;
    private int maxPoolPreparedStatementPerConnectionSize;
    private String filters;
    private String connectionProperties;
}

3、分布式事务管理器配置

@Configuration
@EnableTransactionManagement
public class XATransactionManagerConfig {

    @Bean(name = "userTransaction")
    public UserTransaction userTransaction() throws Throwable {
        UserTransactionImp userTransactionImp = new UserTransactionImp();
        userTransactionImp.setTransactionTimeout(10000);
        return userTransactionImp;
    }

    @Bean(name = "atomikosTransactionManager", initMethod = "init", destroyMethod = "close")
    public TransactionManager atomikosTransactionManager() throws Throwable {
        UserTransactionManager userTransactionManager = new UserTransactionManager();
        userTransactionManager.setForceShutdown(false);
        return userTransactionManager;
    }

    @Bean(name = "transactionManager")
    @DependsOn({ "userTransaction", "atomikosTransactionManager" })
    public PlatformTransactionManager transactionManager() throws Throwable {
        return new JtaTransactionManager(userTransaction(),atomikosTransactionManager());
    }

4、接口调用
controller 方法

    @GetMapping
    public void index(){
//         构造数据
        MessagePackageNo messagePackageNo = new MessagePackageNo();
        messagePackageNo.setNo(99);
        messagePackageNo.setCreateTime(new Date());

        User user = new User();
        user.setAge(25);
        user.setName("lcj");
        user.setCreateTime(new Date());

        indexService.save(messagePackageNo,user);
    }

indexService.save 方法,包含两个不同数据库的调用

@Service
public class IndexService {
    @Autowired
    private MessagePackageNoService messagePackageNoService;

    @Autowired
    private UserService userService;

    /**
     * 保存数据
     *
     * @param messagePackageNo
     * @param user
     */
    @Transactional
    public void save(MessagePackageNo messagePackageNo, User user) {
        messagePackageNoService.insert(messagePackageNo);
        userService.insert(user);
        //int i = 4 / 0; // 除0异常,测试事务
    }
}

基本的demo框架就是这样了,后续上传源码。

相关文章

  • 分布式

    1、分布式事务 1.1 两阶段提交方案/XA方案 Spring+JTA 这种分布式事务方案,比较适合单块应用里,跨...

  • 分布式事务spring+JTA

    1、jdbc操作分布式事务 分布式事务是指事务的参与者、支持事务的服务器、资源管理器以及事务管理器分别位于分布系统...

  • 分布式事务与分布式锁

    一、分布式事务 什么事分布式事务 分布式事务就是指事务的资源分别位于不同的分布式系统的不同节点之上的事务。 分布式...

  • 微服务分布式事务--破局

    微服务架构下分布式事务设计实战 商品 订单 支付 分布式事务->长事务本地事务->短事务 分布式事务: 比如 下...

  • Java事务处理全解析(八)——分布式事务(Spring+JTA

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

  • 分布式事务

    目录 分布式事务解决方案 长事务: saga 短事务: 设计的时候尽量短事务,能不用分布式事务尽量不用,分布式事务...

  • ATOMIKOS+JTA分布式事务记录

    ATOMIKOS+JTA是用来分布式事务的中间件,那么什么是分布式事务呢? 事务,分为单机事务,分布式事务;单机事...

  • 分布式事务

    一、什么是分布式事务 二、分布式事务产生的原因/分布式事务的应用场景 三、分布式事务的基础/理论 CAP/BASE...

  • 微服务 14:初探微服务分布式事务 - Seata

    1:什么是事务,什么是ACID 2:什么是分布式事务 3:分布式事务解决方案 4:Seata 分布式事务框架 5:...

  • 分布式事务的解决方案

    本文从以下几个方面介绍分布式事务的解决方案: 为什么会有分布式事务分布式事务经典模型分布式事务解决方案 为什么会有...

网友评论

      本文标题:分布式事务spring+JTA

      本文链接:https://www.haomeiwen.com/subject/uymadktx.html