新增 spring boot 多数据源用例 支持分布式事务(JTA方式实现)

This commit is contained in:
罗祥 2019-01-27 10:25:59 +08:00
parent 63f0c12af3
commit 81c249e124
7 changed files with 24 additions and 56 deletions

View File

@ -10,7 +10,6 @@ import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import javax.sql.DataSource;
@ -20,8 +19,6 @@ import java.util.Map;
/**
* @author : heibaiying
* @description : 多数据源配置
* 需要特别强调的是以下任意的DataSource的bean都不要用@Primary去修饰包括动态数据源原因是在事务下,spring在DataSourceUtils类中doGetConnection方法中判断获取当前数据源是否持有连接的时候
* 总是会传入用@Primary修饰的数据源如果一个事务下有多个数据源这种情况下就会出现connection复用无法切换数据源, 详见README.md
*/
@Configuration
@MapperScan(basePackages = DataSourceFactory.BASE_PACKAGES, sqlSessionTemplateRef = "sqlSessionTemplate")
@ -33,11 +30,11 @@ public class DataSourceFactory {
/***
* 创建 DruidXADataSource 1
* 创建 DruidXADataSource 1 @ConfigurationProperties自动配置属性
*/
@Bean
@ConfigurationProperties("spring.datasource.druid.db1")
public DataSource DruidDataSourceOne() {
public DataSource druidDataSourceOne() {
return new DruidXADataSource();
}
@ -46,51 +43,34 @@ public class DataSourceFactory {
*/
@Bean
@ConfigurationProperties("spring.datasource.druid.db2")
public DataSource DruidDataSourceTwo() {
public DataSource druidDataSourceTwo() {
return new DruidXADataSource();
}
/**
* 创建支持XA事务的Atomikos数据源1不要用@Primary去修饰
* 创建支持XA事务的Atomikos数据源1
*/
@Bean
public DataSource dataSourceOne(DataSource DruidDataSourceOne) {
public DataSource dataSourceOne(DataSource druidDataSourceOne) {
AtomikosDataSourceBean sourceBean = new AtomikosDataSourceBean();
sourceBean.setXaDataSource((DruidXADataSource) DruidDataSourceOne);
sourceBean.setXaDataSource((DruidXADataSource) druidDataSourceOne);
// 必须为数据源指定唯一标识
sourceBean.setUniqueResourceName("db1");
return sourceBean;
}
/**
* 创建支持XA事务的Atomikos数据源2不要用@Primary去修饰
* 创建支持XA事务的Atomikos数据源2
*/
@Bean
public DataSource dataSourceTwo(DataSource DruidDataSourceTwo) {
public DataSource dataSourceTwo(DataSource druidDataSourceTwo) {
AtomikosDataSourceBean sourceBean = new AtomikosDataSourceBean();
sourceBean.setXaDataSource((DruidXADataSource) DruidDataSourceTwo);
sourceBean.setXaDataSource((DruidXADataSource) druidDataSourceTwo);
sourceBean.setUniqueResourceName("db2");
return sourceBean;
}
/**
* 设置多数据源不要用@Primary去修饰
*/
@Bean
public DataSource dynamicDataSource(DataSource dataSourceOne, DataSource dataSourceTwo) {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
// 设置默认数据源
dynamicDataSource.setDefaultTargetDataSource(dataSourceOne);
// 设置多数据源
Map<Object, Object> dsMap = new HashMap<>();
dsMap.put(Data.DATASOURCE1, dataSourceOne);
dsMap.put(Data.DATASOURCE2, dataSourceTwo);
dynamicDataSource.setTargetDataSources(dsMap);
return dynamicDataSource;
}
/**
* @param dataSourceOne 数据源1
* @return 数据源1的会话工厂

View File

@ -1,17 +0,0 @@
package com.heibaiying.springboot.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* @author : heibaiying
* @description : 动态数据源配置
*/
@Slf4j
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
log.info("当前数据库:{}",DataSourceContextHolder.getDataSourceKey());
return DataSourceContextHolder.getDataSourceKey();
}
}

View File

@ -24,14 +24,14 @@ public class TransactionController {
@RequestMapping("db1/change")
@Transactional
public void changeDb1() {
Programmer programmer = new Programmer(1, "xiaolandb1", 99, 6662.32f, new Date());
Programmer programmer = new Programmer(1, "db1", 99, 6662.32f, new Date());
programmerDao.modify(Data.DATASOURCE1, programmer);
}
@RequestMapping("ts/db1/change")
@Transactional
public void changeTsDb1() {
Programmer programmer = new Programmer(1, "xiaolandb1", 88, 6662.32f, new Date());
Programmer programmer = new Programmer(1, "db1", 88, 6662.32f, new Date());
programmerDao.modify(Data.DATASOURCE1, programmer);
// 抛出异常 查看回滚
int j = 1 / 0;

View File

@ -24,8 +24,8 @@ public class XATransactionController {
@RequestMapping("/db/change")
@Transactional
public void changeDb() {
Programmer programmer01 = new Programmer(1, "xiaolandb1", 100, 6662.32f, new Date());
Programmer programmer02 = new Programmer(1, "xiaohongdb2", 100, 6662.32f, new Date());
Programmer programmer01 = new Programmer(1, "db1", 100, 6662.32f, new Date());
Programmer programmer02 = new Programmer(1, "db2", 100, 6662.32f, new Date());
programmerDao.modify(Data.DATASOURCE1, programmer01);
programmerDao.modify(Data.DATASOURCE2, programmer02);
}
@ -33,8 +33,8 @@ public class XATransactionController {
@RequestMapping("ts/db/change")
@Transactional
public void changeTsDb() {
Programmer programmer01 = new Programmer(1, "xiaolandb1", 99, 6662.32f, new Date());
Programmer programmer02 = new Programmer(1, "xiaohongdb2", 99, 6662.32f, new Date());
Programmer programmer01 = new Programmer(1, "db1", 99, 6662.32f, new Date());
Programmer programmer02 = new Programmer(1, "db2", 99, 6662.32f, new Date());
programmerDao.modify(Data.DATASOURCE1, programmer01);
programmerDao.modify(Data.DATASOURCE2, programmer02);
int i = 1 / 0;

View File

@ -0,0 +1,8 @@
-- 建表语句
create table if not exists programmer (
id int primary key auto_increment,
name varchar(20),
age tinyint,
salary float,
birthday datetime
)

View File

@ -1,3 +0,0 @@
{"id":"10.0.75.1.tm154848923394100001","wasCommitted":true,"participants":[{"uri":"10.0.75.1.tm1","state":"COMMITTING","expires":1548489244031,"resourceName":"db1"},{"uri":"10.0.75.1.tm2","state":"COMMITTING","expires":1548489244031,"resourceName":"db2"}]}
{"id":"10.0.75.1.tm154848923394100001","wasCommitted":true,"participants":[{"uri":"10.0.75.1.tm1","state":"TERMINATED","expires":1548489244061,"resourceName":"db1"},{"uri":"10.0.75.1.tm2","state":"TERMINATED","expires":1548489244061,"resourceName":"db2"}]}
{"id":"10.0.75.1.tm154848925504500002","wasCommitted":false,"participants":[{"uri":"10.0.75.1.tm3","state":"TERMINATED","expires":1548489265019,"resourceName":"db1"},{"uri":"10.0.75.1.tm4","state":"TERMINATED","expires":1548489265019,"resourceName":"db2"}]}