新增 spring boot 多数据源用例 支持分布式事务(JTA方式实现)
This commit is contained in:
parent
63f0c12af3
commit
81c249e124
@ -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的会话工厂
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
)
|
@ -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"}]}
|
Loading…
x
Reference in New Issue
Block a user