不多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"; }
