資料源切換
1.定義AbstractRoutingDataSource,使其能夠支援多個資料源
@Component("dataSource")
@Primary
public class DynamicDataSource extends AbstractRoutingDataSource {
@Autowired
@Qualifier("readDataSource")
private DataSource readDataSource;
@Autowired
@Qualifier("writeDataSource")
private DataSource writeDataSource;
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDbType();
}
@Override
public void afterPropertiesSet() {
Map<Object,Object> map = new HashMap<>();
map.put("readDataSource",readDataSource);
map.put("writeDataSource",writeDataSource);
setTargetDataSources(map);
setDefaultTargetDataSource(writeDataSource);
super.afterPropertiesSet();
}
}
2.資料庫切換類
@Component
@Lazy(false)
public class DataSourceContextHolder {
public static final String WRITE_DATA_SOURCE = "writeDataSource";
public static final String READ_DATA_SOURCE = "readDataSource";
public static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
public static void setDbType(String dbType) {
contextHolder.set(dbType);
}
public static String getDbType() {
return contextHolder.get();
}
public static void clearDbType() {
contextHolder.remove();
}
}
3.通過AOP在切面确定資料源
@Aspect
@Component
@Lazy(false)
@Order(0)
public class SwitchDataSourceAOP {
@Before("execution(* com.mapper.*.*(..)) " )
public void process(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
if (methodName.startsWith("get")
|| other Condition ) {
DataSourceContextHolder.setDbType(DataSourceContextHolder.READ_DATA_SOURCE);
} else {
DataSourceContextHolder.setDbType(DataSourceContextHolder.WRITE_DATA_SOURCE);
}
}
}
4.事務時候選擇資料源
@Configuration
@EnableTransactionManagement(proxyTargetClass = true)
public class DynamicTransactionManagerConfig implements TransactionManagementConfigurer {
@Autowired
private DynamicDataSource dataSource;
@Override
@Bean
public PlatformTransactionManager annotationDrivenTransactionManager() {
return new DynamicDataSourceTransactionManager(dataSource);
}
}
public class DynamicDataSourceTransactionManager extends DataSourceTransactionManager {
public DynamicDataSourceTransactionManager(DataSource dataSource) {
super(dataSource);
}
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
if (!definition.isReadOnly()) {
DataSourceContextHolder.setDbType(DataSourceContextHolder.WRITE_DATA_SOURCE);
}
super.doBegin(transaction, definition);
}
@Override
protected void doCleanupAfterCompletion(Object transaction) {
DataSourceContextHolder.clearDbType();
super.doCleanupAfterCompletion(transaction);
}
}