一、前言
springboot整合多數據源解決分布式事務。1.多數據源采用分包策略
2.全局分布式事務管理:jta-atomikos。
在此記錄下,分享給大家。
二、springboot整合多數據源解決分布式事務
1、pom文件 依賴引入
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
<relativePath />
</parent>
<dependencies>
<!-- SpringBoot 測試 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- SpringBoot web組件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- mybatis 支持 SpringBoot -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<!-- mysql 驅動 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<!-- 全局事務集中管理解決分布式事務 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>
<!-- SpringBoot 自動配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- 注解式插入/構建/優雅代碼 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
</dependency>
</dependencies>
2、 application.yml 新增配置
spring:
datasource:
## 用戶數據庫
user:
url: jdbc:mysql://127.0.0.1:3306/yys_user
username: root
password: 123456
borrowConnectionTimeout: 30
loginTimeout: 30
maintenanceInterval: 60
maxIdleTime: 60
maxLifetime: 20000
maxPoolSize: 25
minPoolSize: 3
uniqueResourceName: userDataSource
testQuery: select 1
## 訂單數據庫
order:
url: jdbc:mysql://127.0.0.1:3306/yys_order
username: root
password: 123456
borrowConnectionTimeout: 30
loginTimeout: 30
maintenanceInterval: 60
maxIdleTime: 60
maxLifeTime: 20000
maxPoolSize: 25
minPoolSize: 3
uniqueResourceName: orderDataSource
testQuery: select 1
3、userConfig.java
@ConfigurationProperties(prefix = "spring.datasource.user")
@Data
public class UserConfig {
private String url;
private String userName;
private String password;
private int minPoolSize;
private int maxPoolSize;
private int maxLifeTime;
private int maxIdleTime;
private int loginTimeout;
private int maintenanceInterval;
private int borrowConnectionTimeout;
private String testQuery;
private String uniqueResourceName;
}
4、userDataSourceConfig.java
/**
* 用戶數據源
* Config
* @author yys
*/
@Configuration
@MapperScan(basePackages = "com.yys.user.mapper", sqlSessionTemplateRef = "userSqlSessionTemplate")
public class UserDataSourceConfig {
/**
* 創建 XADataSource
* @return
*/
@Bean("userDataSource")
public DataSource userDataSource(UserConfig userConfig) throws SQLException {
// 1、創建Mysql XADataSource
MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();
mysqlXaDataSource.setUrl(userConfig.getUrl());
mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
mysqlXaDataSource.setPassword(userConfig.getPassword());
mysqlXaDataSource.setUser(userConfig.getUserName());
mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
// 2、將本地事務注冊到 Atomikos 全局事務
AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
xaDataSource.setXaDataSource(mysqlXaDataSource);
xaDataSource.setUniqueResourceName(userConfig.getUniqueResourceName());
xaDataSource.setMinPoolSize(userConfig.getMinPoolSize());
xaDataSource.setMaxPoolSize(userConfig.getMaxPoolSize());
xaDataSource.setMaxLifetime(userConfig.getMaxLifeTime());
xaDataSource.setBorrowConnectionTimeout(userConfig.getBorrowConnectionTimeout());
xaDataSource.setLoginTimeout(userConfig.getLoginTimeout());
xaDataSource.setMaintenanceInterval(userConfig.getMaintenanceInterval());
xaDataSource.setMaxIdleTime(userConfig.getMaxIdleTime());
xaDataSource.setTestQuery(userConfig.getTestQuery());
return xaDataSource;
}
/**
* 創建 SQL會話工廠
* @param dataSource
* @return
* @throws Exception
*/
@Bean("userSqlSessionFactory")
public SqlSessionFactory userSqlSessionFactory(@Qualifier("userDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
return sqlSessionFactoryBean.getObject();
}
/**
* 創建用戶 SqlSession模板
* @param sqlSessionFactory
* @return
*/
@Bean("userSqlSessionTemplate")
public SqlSessionTemplate userSqlSessionTemplate(@Qualifier("userSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
5、orderConfig.java
@ConfigurationProperties(prefix = "spring.datasource.order")
@Data
public class OrderConfig {
private String url;
private String userName;
private String password;
private int minPoolSize;
private int maxPoolSize;
private int maxLifeTime;
private int maxIdleTime;
private int loginTimeout;
private int maintenanceInterval;
private int borrowConnectionTimeout;
private String testQuery;
private String uniqueResourceName;
}
6、orderDataSourceConfig.java
/**
* 訂單數據源
* Config
* @author yys
*/
@Configuration
@MapperScan(basePackages = "com.yys.order.mapper", sqlSessionTemplateRef = "orderSqlSessionTemplate")
public class OrderDataSourceConfig {
/**
* 創建 XADataSource
* @return
*/
@Bean("orderDataSource")
public DataSource orderDataSource(OrderConfig orderConfig) throws SQLException {
// 1、創建Mysql XADataSource
MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();
mysqlXaDataSource.setUrl(orderConfig.getUrl());
mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
mysqlXaDataSource.setPassword(orderConfig.getPassword());
mysqlXaDataSource.setUser(orderConfig.getUserName());
mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
// 2、將本地事務注冊到 Atomikos 全局事務
AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
xaDataSource.setXaDataSource(mysqlXaDataSource);
xaDataSource.setUniqueResourceName(orderConfig.getUniqueResourceName());
xaDataSource.setMinPoolSize(orderConfig.getMinPoolSize());
xaDataSource.setMaxPoolSize(orderConfig.getMaxPoolSize());
xaDataSource.setMaxLifetime(orderConfig.getMaxLifeTime());
xaDataSource.setBorrowConnectionTimeout(orderConfig.getBorrowConnectionTimeout());
xaDataSource.setLoginTimeout(orderConfig.getLoginTimeout());
xaDataSource.setMaintenanceInterval(orderConfig.getMaintenanceInterval());
xaDataSource.setMaxIdleTime(orderConfig.getMaxIdleTime());
xaDataSource.setTestQuery(orderConfig.getTestQuery());
return xaDataSource;
}
/**
* 創建 SQL會話工廠
* @param dataSource
* @return
* @throws Exception
*/
@Bean("orderSqlSessionFactory")
public SqlSessionFactory orderSqlSessionFactory(@Qualifier("orderDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
return sqlSessionFactoryBean.getObject();
}
/**
* 創建訂單 SqlSession模板
* @param sqlSessionFactory
* @return
*/
@Bean("orderSqlSessionTemplate")
public SqlSessionTemplate orderSqlSessionTemplate(@Qualifier("orderSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
UserService.java
public class UserService {
@Autowired
private UserMapper userMapper;
@Autowired
private OrderMapper orderMapper;
// 全局事務處理器
// 事務底層原理采用aop技術做增強
// 無需再指定某個事務管理器,全交給 Atomikos 全局事務
@Transactional
public Boolean addUser(String name, Integer age, Double amount, String address) {
// 操作用戶庫
int i = userMapper.addUser(name, age);
// 操作訂單庫
int j = orderMapper.addOrder(amount, address);
// 測試事務回滾(age = 0:回滾;age > 0:事務提交)
int flag = 1 / age;
return i > 0 && j > 0;
}
}