参考

基础必读(免费) · dynamic-datasource · 看云 (kancloud.cn)

常见问题之-切换数据源失败 · dynamic-datasource · 看云 (kancloud.cn)

集成ShardingJdbc:集成ShardingJdbc · dynamic-datasource · 看云 (kancloud.cn)

自动读写分离:mybatis下读写分离 · dynamic-datasource · 看云 (kancloud.cn)

数据源

知识库 · dynamic-datasource · 看云 (kancloud.cn)

注入多数据源

1
2
3
4
5
6
7
8
9
10
11
12
public class A{
// 注入多数据源
@Autowired
private DataSource dataSource;

public void dosomething{
//使用的时候需要强转
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;

DataSource master = dynamicRoutingDataSource.getDataSource("master");
}
}

获取当前线程数据源名称

1
DynamicDataSourceContextHolder.peek()

获取当前线程数据源

1
2
3
4
public void dosomething{
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
DataSource datasource=ds.determineDataSource();
}

添加数据源

1
addDataSource(String name, DataSource dataSource)

根据name获取数据源

1
getDataSource(String): DataSource 

获取所有数据源

1
getDataSources(: Map<String, DataSource> 

移除数据源

1
removeDataSource(String): void

获取当前连接的数据库名

1
String schema = DataSourceUtils.getConnection(datasource).getCatalog();

事务

事务常见问题 · dynamic-datasource · 看云 (kancloud.cn)

说明

  • spring原生事务@Transational会保证在事务下整个线程后续拿到的都是同一个connection

Spring原生事务与@DS - 单数据源

先切换使用数据源a再开启事务,整个原生事务内部不管是注解切换还是手动调用代码切换都不能切换,会一直使用a数据源。

所以确认整个事务下不再切换其他数据源

1
2
3
4
5
6
7
8
public class AService {

@DS("a")
@Transational
public void dosomething(){
//some code
}
}

本地事务-多数据源

  • 不要与Spring 原生事务混用
  • B、C上也有@DSTransactional不会有影响
1
2
3
4
5
6
7
8
9
10
public class AService {

@DS("a")
@DSTransactional//最外层开启即可
public void dosomething(){
Amapper.updateSomeThing();
Bservice.dosomething(); //B是另外数据源,然后注解了@DS("b")
Cservice.dosomething(); //C是另外数据源,然后注解了@DS("c")
}
}

多数据源事务

  • 在最外层的方法添加 @DSTransactional,底下调用的各个类该切数据源就正常使用DS切换数据源即可。 就是这么简单。~

  • 只要@DSTransactional注解下任一环节发生异常,则全局多数据源事务回滚。
    如果BC上也有@DSTransactional会有影响吗?答:没有影响的

  • 核心原理就是代理connection,并根据不同数据库获取到一个connection放入ConnectionFactory。 如果成功了整体提交,失败了整体回滚。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//如AService调用BService和CService的方法,A,B,C分别对应不同数据源。

public class AService {

@DS("a")//如果a是默认数据源则不需要DS注解。
@DSTransactional
public void dosomething(){
BService.dosomething();
CService.dosomething();
}
}

public class BService {

@DS("b")
public void dosomething(){
//dosomething
}
}

public class CService {

@DS("c")
public void dosomething(){
//dosomething
}
}