修复 使用从数据源的服务调用其他服务会导致后续数据源使用异常
更新多数据非Master数据源使用中调用任何其他数据源导致后续sql执行在Master数据源的bug
```java
#ServiceImpl1.java
@Service
@DataSource("SLAVE1")
public class ServiceImpl1{
public void doSomething1(){
}
}
#ServiceImpl2.java
@Service
@DataSource("SLAVE2")
public class ServiceImpl2{
@Autowired
private ServiceImpl1 service1;
public void doSomething2(){
// SLAVE2
log.debug("当前数据源:{}",DynamicDataSourceContextHolder.getDataSourceType());
//数据源注解生效 并在方法执行后调用 clearDataSourceType
service1.doSomething1();
//修改前 调用了 clearDataSourceType会清理数据源的标记 此处会打印 MASTER(默认值) 导致本方法后续使用MASTER执行sql 而不是注解上的 SLAVE2 不符合预期
//修改前 调用了 clearDataSourceType仅会清理一层数据源结构 此处打印的依然是 SLAVE2 后续使用 SLAVE2数据源执行sql
log.debug("当前数据源:{}",DynamicDataSourceContextHolder.getDataSourceType());
}
}
```
Signed-off-by: 尘埃落定 <wlx_xyw@163.com>
This commit is contained in:
parent
eef7ef6544
commit
39e79bb88c
|
|
@ -3,6 +3,8 @@ package com.ruoyi.common.config.datasource;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据源切换处理
|
* 数据源切换处理
|
||||||
*
|
*
|
||||||
|
|
@ -16,15 +18,17 @@ public class DynamicDataSourceContextHolder
|
||||||
* 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本,
|
* 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本,
|
||||||
* 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
|
* 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
|
||||||
*/
|
*/
|
||||||
private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();
|
private static final ThreadLocal<DataSourceTypeStruct> CONTEXT_HOLDER = new ThreadLocal<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置数据源的变量
|
* 设置数据源的变量
|
||||||
*/
|
*/
|
||||||
public static void setDataSourceType(String dsType)
|
public static void setDataSourceType(String dsType)
|
||||||
{
|
{
|
||||||
log.info("切换到{}数据源", dsType);
|
DataSourceTypeStruct dataSourceTypeStruct = Optional.ofNullable(CONTEXT_HOLDER.get()).orElse(new DataSourceTypeStruct(DataSourceType.MASTER.name()));//最顶层默认为 MASTER 数据源
|
||||||
CONTEXT_HOLDER.set(dsType);
|
dataSourceTypeStruct.setDsType(dsType);
|
||||||
|
log.info("切换到{}数据源,当前:{}", dsType,dataSourceTypeStruct);
|
||||||
|
CONTEXT_HOLDER.set(dataSourceTypeStruct);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -32,7 +36,8 @@ public class DynamicDataSourceContextHolder
|
||||||
*/
|
*/
|
||||||
public static String getDataSourceType()
|
public static String getDataSourceType()
|
||||||
{
|
{
|
||||||
return CONTEXT_HOLDER.get();
|
DataSourceTypeStruct dataSourceTypeStruct = Optional.ofNullable(CONTEXT_HOLDER.get()).orElse(new DataSourceTypeStruct(DataSourceType.MASTER.name()));//最顶层默认为 MASTER 数据源
|
||||||
|
return dataSourceTypeStruct.getDsType();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -40,6 +45,44 @@ public class DynamicDataSourceContextHolder
|
||||||
*/
|
*/
|
||||||
public static void clearDataSourceType()
|
public static void clearDataSourceType()
|
||||||
{
|
{
|
||||||
CONTEXT_HOLDER.remove();
|
DataSourceTypeStruct dataSourceTypeStruct = Optional.ofNullable(CONTEXT_HOLDER.get()).orElse(new DataSourceTypeStruct(DataSourceType.MASTER.name()));
|
||||||
|
dataSourceTypeStruct.clearDsType();
|
||||||
|
log.info("清理一层数据源,当前:{}", dataSourceTypeStruct);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 创建层级结构 保存数据源
|
||||||
|
*/
|
||||||
|
static class DataSourceTypeStruct{
|
||||||
|
private final String dsType;
|
||||||
|
private DataSourceTypeStruct next;
|
||||||
|
protected DataSourceTypeStruct(String dsType){
|
||||||
|
this.dsType = dsType;
|
||||||
|
}
|
||||||
|
public String getDsType(){//获得最底层DataSourceTypeStruct的dsType
|
||||||
|
if(null!=next){
|
||||||
|
return next.getDsType();
|
||||||
|
}
|
||||||
|
return dsType;
|
||||||
|
}
|
||||||
|
public void setDsType(String dsType){//设置最底层DataSourceTypeStruct的dsType
|
||||||
|
if(null!=next){
|
||||||
|
next.setDsType(dsType);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
next = new DataSourceTypeStruct(dsType);
|
||||||
|
}
|
||||||
|
public void clearDsType(){//清理最底层的DataSourceTypeStruct 层级-1
|
||||||
|
if(null!=next){
|
||||||
|
if(null==next.next){
|
||||||
|
next=null;
|
||||||
|
}else{
|
||||||
|
next.clearDsType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String toString(){
|
||||||
|
return dsType+(null==next?"":("->"+next));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue