DataSource
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
String value() default "";
}
DataSourceAspect
@Aspect
@Component
@Order(1)
public class DataSourceAspect {
@Pointcut("@annotation(com.xiaomi.nr.order.infra.config.DataSource)")
public void dataSourcePointCut() {
}
@Around("dataSourcePointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
if(DynamicDataSource.getDataSource() != null) {
return point.proceed();
}
DataSource dataSource = method.getAnnotation(DataSource.class);
if (dataSource == null) {
DynamicDataSource.setDataSource("xm-master");
} else {
DynamicDataSource.setDataSource(dataSource.value());
}
try {
return point.proceed();
} finally {
DynamicDataSource.clearDataSource();
}
}
}
DynamicDataSource
public class DynamicDataSource extends AbstractRoutingDataSource {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
super.setDefaultTargetDataSource(defaultTargetDataSource);
super.setTargetDataSources(targetDataSources);
super.afterPropertiesSet();
}
@Override
protected Object determineCurrentLookupKey() {
return getDataSource();
}
public static void setDataSource(String dataSource) {
contextHolder.set(dataSource);
}
public static String getDataSource() {
return contextHolder.get();
}
public static void clearDataSource() {
contextHolder.remove();
}
}
DynamicDataSourceConfig
@Configuration
@MapperScan(basePackages = {"com.xiaomi.nr.order.infra.repository.dao"}, sqlSessionFactoryRef = "xmSqlSessionFactory")
public class DynamicDataSourceConfig {
@Bean(name = "xmmDatasource")
@ConfigurationProperties("spring.xmm-datasource")
public DataSource xmDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "xmsDatasource")
@ConfigurationProperties("spring.xms-datasource")
public DataSource xmsDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "storemDatasource")
@ConfigurationProperties("spring.storem-datasource")
public DataSource storemDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "storesDatasource")
@ConfigurationProperties("spring.stores-datasource")
public DataSource storesDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "xm_pls")
@ConfigurationProperties("spring.xmpls-datasource")
public DataSource plsDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "xm_shop_fcode")
@ConfigurationProperties("spring.xmfcode-datasource")
public DataSource xmfcodeDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "xmDatasource")
public DynamicDataSource dataSource(DataSource xmmDatasource, DataSource xmsDatasource) {
Map<Object, Object> targetDataSources = new HashMap<Object,Object>();
targetDataSources.put("xm-master",xmmDatasource);
targetDataSources.put("xm-slave", xmsDatasource);
targetDataSources.put("store-master", storemDataSource());
targetDataSources.put("store-slave", storesDataSource());
targetDataSources.put("xmpls-master", plsDataSource());
targetDataSources.put("xmpls-slave", plsDataSource());
targetDataSources.put("xmfcode-master", xmfcodeDataSource());
return new DynamicDataSource(xmmDatasource, targetDataSources);
}
@Primary
@Bean(name = "xmSqlSessionFactory")
public SqlSessionFactory mysqlSqlSessionFactory(@Qualifier("xmDatasource") DataSource dataSource)
throws Exception {
final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mybatis/mapper/*.xml"));
sessionFactory.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
return sessionFactory.getObject();
}
@Bean(name = "xmTransactionManager")
public PlatformTransactionManager prodTransactionManager(@Qualifier("xmDatasource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
SyncDataService
@DataSource("xm-master")
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, transactionManager = "xmTransactionManager")
public void t2xOnlineStore(T2XSyncOrder message) {
message.generateCompressData();
xmOrderMapper.insert(message.getXmOrder());
message.getXmOrderExtend().forEach(extend -> xmOrderExtendMapper.insert(extend));
message.getXmOrderItem().forEach(item -> xmOrderItemMapper.insert(item));
xmOrderExtentionsMapper.insert(message.getXmOrderExtentions());
if (message.getXmSubsidyApplications() != null) {
xmSubsidyApplicationsMapper.insert(message.getXmSubsidyApplications());
}
log.info("t2x同步门店订单完成。订单号:【{}】", message.getXmOrder().getOrderId());
}
XmOrderLogMapper
@Mapper
@Repository
public interface XmOrderLogMapper {
@DataSource("xm-master")
void insert(XmOrderLog xmOrderLog);
@DataSource("xm-slave")
@Select("select * from xm_order_log where order_id = #{orderId} and user_id = #{userId}")
List<XmOrderLog> getXmOrderLog(@Param("userId") long userId, @Param("orderId") long orderId);
@DataSource("oldxm-slave")
@Select("select * from xm_order_log where order_id = #{orderId} and user_id = #{userId}")
List<XmOrderLog> getOLdXmOrderLog(@Param("userId") long userId, @Param("orderId") long orderId);
}