springboot2.0 解决多数据源分布式事务问题

2021-03-04 10:28

阅读:515

标签:lombok   ==   pom   ppi   unit   web   atomikos   一个数据库   mapper   

大家都知道,在多数据源的项目中可能会发生的事务问题,因为一个库的事务不可能去操作另一个数据库的事务嘛,这里使用传统的分布式事务解决方案:SpringBoot+JTA+Atomikos 

使用atomikos对数据库的事务进行统一的管理,但是这套解决方案不适合微服务,需要拿到数据源然后注册到同一个全局事务里面去

好,那我们如何配置呢?话不多说直接上代码

pom.xml配置

技术图片技术图片
 1  2  3          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
 4     4.0.0 5      6         org.springframework.boot 7         spring-boot-starter-parent
 8         2.2.10.RELEASE 9         10     11     com.wuwu12     cboot
13     0.0.1-SNAPSHOT14     cboot15     this project for Spring Boot16 
17     18         1.819     20 
21     22         23             org.springframework.boot24             spring-boot-starter-data-jdbc
25         26         27             org.springframework.boot28             spring-boot-starter-web
29         30 
31         
32         33             org.springframework.boot34             spring-boot-starter-jta-atomikos
35         36         
37         38             org.mybatis.spring.boot39             mybatis-spring-boot-starter
40             2.0.041         42         
43         44             org.projectlombok45             lombok
46             1.18.1247             provided48         49 
50         51             mysql52             mysql-connector-java
53             runtime54         55 
56         57             ch.qos.logback58             logback-core
59             1.1.360         61         62             ch.qos.logback63             logback-access
64             1.1.365         66         67             ch.qos.logback68             logback-classic
69             1.1.370         71 
72         73             org.springframework.boot74             spring-boot-starter-test
75             test76             77                 78                     org.junit.vintage79                     junit-vintage-engine
80                 81             82         83     84 
85     86         87             88                 org.springframework.boot89                 spring-boot-maven-plugin
90             91         92     93 
94 
View Code

application.properties配置

技术图片技术图片
 1 server.port=8090
 2 server.servlet.context-path=/
 3 #单数据源
 4 #spring.datasource.driverClassName=com.mysql.jdbc.Driver
 5 #spring.datasource.url=jdbc:mysql://localhost:3306/cboot?useUnicode=true&characterEncoding=UTF-8
 6 #spring.datasource.username=root
 7 #spring.datasource.password=root
 8 
 9 #多数据源-订单
10 spring.datasource.order.driverClassName=com.mysql.jdbc.Driver
11 spring.datasource.order.url=jdbc:mysql://localhost:3306/cboot?useUnicode=true&characterEncoding=UTF-8
12 spring.datasource.order.username=root
13 spring.datasource.order.password=root
14 
15 #多数据源-会员
16 spring.datasource.member.driverClassName=com.mysql.jdbc.Driver
17 spring.datasource.member.url=jdbc:mysql://localhost:3306/cboot1?useUnicode=true&characterEncoding=UTF-8
18 spring.datasource.member.username=root
19 spring.datasource.member.password=root
View Code

MemberConfig以及OrderConfig的配置bean

技术图片技术图片
 1 package com.wuwu.cboot.config;
 2 
 3 import lombok.Data;
 4 import org.springframework.boot.context.properties.ConfigurationProperties;
 5 
 6 /**
 7  * @Description:会员数据库连接属性
 8  * @author: wph
 9  * @Version: 1.0
10  * @date: 2021/1/15
11  */
12 @Data
13 @ConfigurationProperties(prefix = "spring.datasource.member")
14 public class MemberConfig {
15 
16     private String url;
17     private String password;
18     private String username;
19     private String driverClassName;
20 }
View Code
技术图片技术图片
 1 package com.wuwu.cboot.config;
 2 
 3 import lombok.Data;
 4 import org.springframework.boot.context.properties.ConfigurationProperties;
 5 
 6 /**
 7  * @Description:订单数据库连接属性
 8  * @author: wph
 9  * @Version: 1.0
10  * @date: 2021/1/15
11  */
12 @Data
13 @ConfigurationProperties(prefix = "spring.datasource.order")
14 public class OrderConfig {
15 
16     private String url;
17     private String password;
18     private String username;
19     private String driverClassName;
20 }
View Code

会员数据源MemberDataSourceConfig配置

技术图片技术图片
 1 package com.wuwu.cboot.config;
 2 
 3 import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource;
 4 import lombok.SneakyThrows;
 5 import org.apache.ibatis.session.SqlSessionFactory;
 6 import org.mybatis.spring.SqlSessionFactoryBean;
 7 import org.mybatis.spring.SqlSessionTemplate;
 8 import org.mybatis.spring.annotation.MapperScan;
 9 import org.springframework.beans.factory.annotation.Qualifier;
10 import org.springframework.boot.jta.atomikos.AtomikosDataSourceBean;
11 import org.springframework.context.annotation.Bean;
12 import org.springframework.context.annotation.Configuration;
13 
14 import javax.sql.DataSource;
15 
16 /**
17  * @Description:会员数据源配置
18  * @author: wph
19  * @Version: 1.0
20  * @date: 2021/1/12
21  */
22 @Configuration
23 @MapperScan(basePackages = "com.wuwu.cboot.member.mapper",sqlSessionTemplateRef = "memberSqlSessionTemplate")
24 public class MemberDataSourceConfig {
25 
26     /**
27      * @Description: 配置会员数据源
28      * @author: wph
29      * @date: 2021/1/15
30      * @param memberConfig
31      * @return javax.sql.DataSource
32      */
33     @Bean("memberDataSource")
34     public DataSource memberDataSource(MemberConfig memberConfig){
35         //1.创建会员的xaDataSource
36         MysqlXADataSource xaDataSource = new MysqlXADataSource();
37         xaDataSource.setPassword(memberConfig.getPassword());
38         xaDataSource.setUser(memberConfig.getUsername());
39         xaDataSource.setUrl(memberConfig.getUrl());
40         xaDataSource.setPinGlobalTxToPhysicalConnection(true);
41 
42         //2.将会员的xaDataSource注册到全局事务上
43         AtomikosDataSourceBean dataSource = new AtomikosDataSourceBean();
44         dataSource.setXaDataSource(xaDataSource);
45 
46         return dataSource;
47     }
48 
49     /**
50      * @Description: 将会员sqlSessionFactory注入到容器中
51      * @author: wph
52      * @date: 2021/1/13
53      * @param dataSource 
54      * @return org.apache.ibatis.session.SqlSessionFactory
55      */
56     @SneakyThrows(Exception.class)
57     @Bean("memberSqlSessionFactory")
58     public SqlSessionFactory memberSqlSessionFactory(@Qualifier("memberDataSource")DataSource dataSource){
59         SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
60         sqlSessionFactoryBean.setDataSource(dataSource);
61         return sqlSessionFactoryBean.getObject();
62     }
63 
64     /**
65      * @Description: 创建SqlSessionTemplate模板
66      * @author: wph
67      * @date: 2021/1/18
68      * @param sqlSessionFactory
69      * @return org.mybatis.spring.SqlSessionTemplate
70      */
71     @Bean("memberSqlSessionTemplate")
72     public SqlSessionTemplate memberSqlSessionTemplate(@Qualifier("memberSqlSessionFactory") SqlSessionFactory sqlSessionFactory){
73         return new SqlSessionTemplate(sqlSessionFactory);
74     }
75 
76 }
View Code

订单数据源OrderDataSourceConfig配置

技术图片技术图片
 1 package com.wuwu.cboot.config;
 2 
 3 import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource;
 4 import lombok.SneakyThrows;
 5 import org.apache.ibatis.session.SqlSessionFactory;
 6 import org.mybatis.spring.SqlSessionFactoryBean;
 7 import org.mybatis.spring.SqlSessionTemplate;
 8 import org.mybatis.spring.annotation.MapperScan;
 9 import org.springframework.beans.factory.annotation.Qualifier;
10 import org.springframework.boot.jta.atomikos.AtomikosDataSourceBean;
11 import org.springframework.context.annotation.Bean;
12 import org.springframework.context.annotation.Configuration;
13 
14 import javax.sql.DataSource;
15 
16 /**
17  * @Description:订单数据源配置
18  * @author: wph
19  * @Version: 1.0
20  * @date: 2021/1/15
21  */
22 @Configuration
23 @MapperScan(basePackages = "com.wuwu.cboot.order.mapper",sqlSessionFactoryRef = "orderSqlSessionFactory")
24 public class OrderDataSourceConfig {
25 
26     /**
27      * @Description: 配置订单数据源
28      * @author: wph
29      * @date: 2021/1/15
30      * @param orderConfig
31      * @return javax.sql.DataSource
32      */
33     @Bean("orderDataSource")
34     public DataSource orderDataSource(OrderConfig orderConfig){
35         //1.创建订单xaDataSource
36         MysqlXADataSource xaDataSource = new MysqlXADataSource();
37         xaDataSource.setUrl(orderConfig.getUrl());
38         xaDataSource.setUser(orderConfig.getUsername());
39         xaDataSource.setPassword(orderConfig.getPassword());
40         xaDataSource.setPinGlobalTxToPhysicalConnection(true);
41 
42         //将xaDataSource注册到全局事务
43         AtomikosDataSourceBean dataSource = new AtomikosDataSourceBean();
44         dataSource.setXaDataSource(xaDataSource);
45         return dataSource;
46     }
47 
48     /**
49      * @Description: 配置session工厂
50      * @author: wph
51      * @date: 2021/1/18
52      * @param dataSource
53      * @return org.apache.ibatis.session.SqlSessionFactory
54      */
55     @SneakyThrows
56     @Bean("orderSqlSessionFactory")
57     public SqlSessionFactory orderSqlSessionFactory(@Qualifier("orderDataSource") DataSource dataSource){
58         SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
59         sqlSessionFactoryBean.setDataSource(dataSource);
60         return sqlSessionFactoryBean.getObject();
61     }
62 
63     /**
64      * @Description: 创建SqlSessionTemplate模板
65      * @author: wph
66      * @date: 2021/1/18
67      * @param sqlSessionFactory
68      * @return org.mybatis.spring.SqlSessionTemplate
69      */
70     @Bean("orderSqlSessionTemplate")
71     public SqlSessionTemplate orderSqlSessionTemplate(@Qualifier("orderSqlSessionFactory") SqlSessionFactory sqlSessionFactory){
72         return new SqlSessionTemplate(sqlSessionFactory);
73     }
74 
75 }
View Code

controller层

技术图片技术图片
 1 package com.wuwu.cboot.controller;
 2 
 3 import com.wuwu.cboot.service.MemberService;
 4 import org.springframework.beans.factory.annotation.Autowired;
 5 import org.springframework.web.bind.annotation.RequestMapping;
 6 import org.springframework.web.bind.annotation.RestController;
 7 
 8 /**
 9  * @Description:会员控制层
10  * @author: wph
11  * @Version: 1.0
12  * @date: 2020/10/26
13  */
14 @RestController
15 public class MemberController {
16 
17     @Autowired
18     private MemberService memberService;
19 
20     /**
21      * @Description: 新增会员用户
22      * @author: wph
23      * @date: 2021/1/20
24      * @param age
25      * @param name
26      * @return java.lang.Object
27      */
28     @RequestMapping("/saveMember")
29     public Object saveMember(int age,String name){
30         return memberService.saveMember(age,name);
31     }
32 }
View Code

service实现

技术图片技术图片
 1 package com.wuwu.cboot.service.impl;
 2 
 3 import com.wuwu.cboot.member.mapper.MemberMapper;
 4 import com.wuwu.cboot.order.mapper.OrderMemberMapper;
 5 import com.wuwu.cboot.service.MemberService;
 6 import org.springframework.stereotype.Service;
 7 import org.springframework.transaction.annotation.Transactional;
 8 
 9 import javax.annotation.Resource;
10 
11 /**
12  * @Description:
13  * @author: wph
14  * @Version: 1.0
15  * @date: 2021/1/12
16  */
17 @Service
18 public class MemberServiceImpl implements MemberService {
19 
20     @Resource
21     private OrderMemberMapper orderMemberMapper;
22     @Resource
23     private MemberMapper memberMapper;
24 
25     @Transactional
26     public String saveMember(int age,String name){
27         //调用会员接口
28         memberMapper.saveMember(age, name);
29         //调用订单接口
30         int i = orderMemberMapper.saveOrder(123, "dawfa");
31         int num = 13 / 0;
32         return i == 1 ? "true" : "false";
33     }
34 }
View Code

mapper层

技术图片技术图片
 1 package com.wuwu.cboot.member.mapper;
 2 
 3 import org.apache.ibatis.annotations.Insert;
 4 import org.apache.ibatis.annotations.Mapper;
 5 
 6 @Mapper
 7 public interface MemberMapper {
 8 
 9     @Insert("insert into member (age,name) values(#{age},#{name})")
10     int saveMember(int age, String name);
View Code
技术图片技术图片
 1 package com.wuwu.cboot.order.mapper;
 2 
 3 import org.apache.ibatis.annotations.Insert;
 4 import org.mybatis.spring.annotation.MapperScan;
 5 
 6 @MapperScan
 7 public interface OrderMemberMapper {
 8 
 9     @Insert("insert into order_member (order_id,order_code) values(#{orderId},#{orderCode})")
10     int saveOrder(int orderId, String orderCode);
11 }
View Code

项目启动类

技术图片技术图片
 1 package com.wuwu.cboot;
 2 
 3 import com.wuwu.cboot.config.MemberConfig;
 4 import com.wuwu.cboot.config.OrderConfig;
 5 import org.springframework.boot.SpringApplication;
 6 import org.springframework.boot.autoconfigure.SpringBootApplication;
 7 import org.springframework.boot.context.properties.EnableConfigurationProperties;
 8 
 9 @SpringBootApplication
10 @EnableConfigurationProperties({MemberConfig.class, OrderConfig.class})
11 public class CbootApplication {
12 
13     public static void main(String[] args) {
14         SpringApplication.run(CbootApplication.class, args);
15     }
16 
17 }
View Code

最后附上项目结构目录,如图

技术图片

ok,直接启动运行即可

springboot2.0 解决多数据源分布式事务问题

标签:lombok   ==   pom   ppi   unit   web   atomikos   一个数据库   mapper   

原文地址:https://www.cnblogs.com/w-wu/p/14303119.html


评论


亲,登录后才可以留言!