一、前言
springboot整合多數(shù)據(jù)源解決分布式事務(wù)合武。
?????1.多數(shù)據(jù)源采用分包策略
?????2.全局分布式事務(wù)管理:jta-atomikos。
在此記錄下,分享給大家客给。
二袜漩、springboot整合多數(shù)據(jù)源解決分布式事務(wù)
1甜害、pom文件 依賴引入
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
<relativePath />
</parent>
<dependencies>
<!-- SpringBoot 測(cè)試 -->
<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 驅(qū)動(dòng) -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<!-- 全局事務(wù)集中管理 解決分布式事務(wù) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>
<!-- SpringBoot 自動(dòng)配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- 注解式 插入/構(gòu)建/優(yōu)雅代碼 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
</dependency>
</dependencies>
2通砍、 application.yml 新增配置
spring:
datasource:
## 用戶數(shù)據(jù)庫(kù)
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
## 訂單數(shù)據(jù)庫(kù)
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
/**
* 用戶數(shù)據(jù)源
* Config
* @author yys
*/
@Configuration
@MapperScan(basePackages = "com.yys.user.mapper", sqlSessionTemplateRef = "userSqlSessionTemplate")
public class UserDataSourceConfig {
/**
* 創(chuàng)建 XADataSource
* @return
*/
@Bean("userDataSource")
public DataSource userDataSource(UserConfig userConfig) throws SQLException {
// 1辕近、創(chuàng)建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、將本地事務(wù)注冊(cè)到 Atomikos 全局事務(wù)
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;
}
/**
* 創(chuàng)建 SQL會(huì)話工廠
* @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();
}
/**
* 創(chuàng)建用戶 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
/**
* 訂單數(shù)據(jù)源
* Config
* @author yys
*/
@Configuration
@MapperScan(basePackages = "com.yys.order.mapper", sqlSessionTemplateRef = "orderSqlSessionTemplate")
public class OrderDataSourceConfig {
/**
* 創(chuàng)建 XADataSource
* @return
*/
@Bean("orderDataSource")
public DataSource orderDataSource(OrderConfig orderConfig) throws SQLException {
// 1、創(chuàng)建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椿疗、將本地事務(wù)注冊(cè)到 Atomikos 全局事務(wù)
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;
}
/**
* 創(chuàng)建 SQL會(huì)話工廠
* @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();
}
/**
* 創(chuàng)建訂單 SqlSession模板
* @param sqlSessionFactory
* @return
*/
@Bean("orderSqlSessionTemplate")
public SqlSessionTemplate orderSqlSessionTemplate(@Qualifier("orderSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
7漏峰、MybatisController.java
/**
* 多數(shù)據(jù)源解決分布式事務(wù)測(cè)試
* Controller
* @author yys
*/
@RestController
@RequestMapping("/add")
public class MybatisController {
@Autowired
private UserService userService;
@Autowired
private OrderService orderService;
/**
* 新增用戶并生成訂單(解決分布式事務(wù)問(wèn)題)
* @return
*/
@RequestMapping("/user")
public String addUser(String name, Integer age, Double amount, String address) {
return userService.addUser(name, age, amount, address) ? "success" : "fail";
}
}
8、UserService.java
/**
* 用戶管理
* Service
* @author yys
*/
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
@Autowired
private OrderMapper orderMapper;
// 全局事務(wù)處理器
// 事務(wù)底層原理采用aop技術(shù)做增強(qiáng)
// 無(wú)需再指定某個(gè)事務(wù)管理器届榄,全交給 Atomikos 全局事務(wù)
@Transactional
public Boolean addUser(String name, Integer age, Double amount, String address) {
// 操作用戶庫(kù)
int i = userMapper.addUser(name, age);
// 操作訂單庫(kù)
int j = orderMapper.addOrder(amount, address);
// 測(cè)試事務(wù)回滾(age = 0:回滾浅乔;age > 0:事務(wù)提交)
int flag = 1 / age;
return i > 0 && j > 0;
}
}
9、UserMapper.java
/**
* 用戶管理
* Mapper
* @author yys
*/
public interface UserMapper {
@Insert("INSERT INTO user VALUES (NULL, #{name}, #{age}, 1, NOW(), NOW())")
int addUser(@Param("name") String name, @Param("age") Integer age);
}
10铝条、OrderMapper.java
/**
* 訂單管理
* Mapper
* @author yys
*/
public interface OrderMapper {
// order為數(shù)據(jù)庫(kù)關(guān)鍵字靖苇,記得使用``
@Insert("INSERT INTO `order` VALUES (NULL, #{amount}, #{address}, 1, NOW(), NOW())")
int addOrder(@Param("amount") Double amount, @Param("address") String address);
}
11、啟動(dòng)類(lèi)
@SpringBootApplication
@MapperScan("com.yys.mapper")
public class YysApp {
public static void main(String[] args) {
SpringApplication.run(YysApp.class, args);
}
}
12班缰、初始化sql文件
-- Database:yys_user
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT 'ID贤壁,自增列',
`name` varchar(32) NOT NULL COMMENT '用戶名',
`age` int(11) NOT NULL COMMENT '用戶年齡',
`status` tinyint(2) NOT NULL DEFAULT '1' COMMENT '狀態(tài):-1-刪除;1-正常鲁捏;',
`create_time` datetime NOT NULL COMMENT '創(chuàng)建時(shí)間',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時(shí)間',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;
-- Database:yys_order
DROP TABLE IF EXISTS `order`;
CREATE TABLE `order` (
`id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT 'ID芯砸,自增列',
`amount` double(11,2) NOT NULL COMMENT '訂單金額',
`address` varchar(32) NOT NULL COMMENT '地址',
`status` tinyint(2) NOT NULL DEFAULT '1' COMMENT '狀態(tài):-1-刪除萧芙;1-正常给梅;',
`create_time` datetime NOT NULL COMMENT '創(chuàng)建時(shí)間',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時(shí)間',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;
13、測(cè)試
http://localhost:8080/add/user?name=古猿&age=0&amount=12.02&address=南方
a双揪、頁(yè)面結(jié)果 - 如下圖所示 :
b动羽、數(shù)據(jù)庫(kù)結(jié)果 - 如下圖所示 :
http://localhost:8080/add/user?name=古猿&age=18&amount=12.02&address=南方
a、頁(yè)面結(jié)果 - 如下圖所示 :
b渔期、數(shù)據(jù)庫(kù)結(jié)果 - 如下圖所示 :