不多BB,直接上代码:
public class DataSourceKey { /** * 用户数据源 */ public final static String USER = "userDataSource"; /** * 报表数据源 */ public final static String REPORT = "reportDataSource"; /** * 所有数据源的集合 */ final static List<String> SOURCES = ImmutableList.of(USER, REPORT); /** * 根据包名找到数据源, 多数据源的前缀不能存在相同的。 例: user -> userDataSource * * @param pack 包名 * @return 数据源名 */ public static String getDataSourceKey(String pack) { return SOURCES.stream().filter(s -> s.startsWith(pack)).findFirst().orElse(USER); } }
@Component @Aspect @Order(-1) @Slf4j public class DynamicDataSourceAspect { @Pointcut("execution(* com.in.g.data.mapper..*.*(..))") public void dataSourcePointcut() { } @Before("dataSourcePointcut()") public void doBefore(JoinPoint point) throws Throwable { log.debug("切换数据源开始。。。。。。。。。。。。"); Package pack = point.getSignature().getDeclaringType().getPackage(); String str = StringUtils.substringAfterLast(pack.getName(), "."); String dataSourceKey = DataSourceKey.getDataSourceKey(str); DynamicDataSourceHolder.set(dataSourceKey); log.debug("切换数据源成功,当前数据源:{}", dataSourceKey); } @After("dataSourcePointcut()") public void doAfterReturning() throws Throwable { DynamicDataSourceHolder.clear(); } }
/** * 动态数据源持有者 */ public class DynamicDataSourceHolder { public static ThreadLocal<String> keyHolder = new ThreadLocal<>(); public static void clear() { keyHolder.remove(); } public static void set(String key) { keyHolder.set(key); } public static String get() { return keyHolder.get(); } }
/** * 动态数据源配置 */ public class DynamicRoutingDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DynamicDataSourceHolder.get(); } }
//正确的代码 --这里偷懒了,直接controller调用dao层
@GetMapping("/testdb") public String testDateSources(){
//缩小事务的范围 add(); rptFieldMapper.selectxxxx(); return "sss"; } @Transactional(rollbackFor = Exception.class) public void add() {
userMapper.insertXXXX(xxxx);
}
//错误的代码,@Transactional注解会导致 数据源切换失败 @GetMapping("/testdb") @Transactional(rollbackFor = Exception.class) public String testDateSources(){ userMapper.insertXXXX(xxxx); rptFieldMapper.selectXXXX(); return "sss"; }