SpringBoot的多数据源实现以实现AbstractRoutingDataSource#determineCurrentLookupKey()来达到多个数据源动态切换的目的。
网上有很多的文章可以获取具体方法,就不在讲了。
项目中需要用到多数据源MySQL和SQLServer两个数据库,系统要保持两个数据库的数据同步,就需要来回切数据源来操作数据库。
刚写好了数据从MySQL同步到SQLServer中的代码,测试发现数据源不能切换到SQLServer数据库连接,排查问题~~省略n多个小时后,源码解析等理论就不写了(重要的是不会写)直接上修改方案
CSDN查到的方案有:
数据源切换和事务的注入顺序问题,像下面这样的,加入@Order注解。测试无效(可能我搭的架构有问题),主要是事务的原因导致数据源切换无效,可以在业务层上面加上不支持事务,就可以解决这个问题。
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void excuteProject(String projectId, List<String> excuValue,
String start, String end, int interval, String modeFlag) throws Exception {
@Component
@Aspect
@Order(1)
public class EtlDataSourceAspect {
private static final Logger LOGGER = LoggerFactory.getLogger(EtlDataSourceAspect.class);
@Pointcut(value = "bean(etl_datasource_service)")
public void execPoint() {
}
@Around(value = "execPoint()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
LOGGER.info("切面拦截到变量");
MethodSignature methodSignature = (MethodSignature)pjp.getSignature();
String methodName = methodSignature.getMethod().getName();
LOGGER.info("{}切面拦截到变量", methodName);
if (EtlDatasourceServiceImpl.hasConfig) {
LOGGER.info("配置了配置中心");
DynamicDataSourceContextHolder.push("ops");
}
Object returnVal;
try {
returnVal = pjp.proceed();
} finally {
DynamicDataSourceContextHolder.clear();
}
return returnVal;
}
}
Mapper(Dao)层切换数据源,反正我没找到怎么个用法,所以没有测试。
还有下面的这种写法。测试有效的
public EtlDatasource selectDatasource(String datasourceId) throws Exception{
try {
return etlDatasourceService.getByProjectId(datasourceId);
} catch (Exception e) {
throw ApiException.createBizEx("数据源找不到");
}
}
// 这种调用保存数据的方法,有效切换数据源
@Override
@DataSource(name = DataSourceDef.OPS)
public EtlDatasource getByProjectId(String datasourceId) throws Exception {
EtlDatasource etlDatasource = getDao().getByProjectId(datasourceId);
return etlDatasource;
}