项目中如何使用java代码配置多数据源,并能指定某些查询使用某个数据源
·
项目中如何使用java代码配置多数据源,并能指定某些查询使用某个数据源
1、首先需要思考,配置多数据源需要实现什么?是不是要根据不同的查询来指定是查主库还是查从库
2、那在学过的知识中,什么方法可以实现在执行某个查询前根据指定的数据库查询?Aspect(切面)
实现思路:
1、多数据源场景,怎么指定使用哪个数据源呢?
需要有个注解,通过注解来指定
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
String name() default "";
}
2、定义切面处理类
@Aspect
@Component
public class DataSourceAspect implements Ordered {
protected Logger logger = LoggerFactory.getLogger(getClass());
@Point("@annotation(多数据源注解接口所在完整类名-包名.类名)")
public void dataSourcePointCut(){
//nothing
}
@Around("dataSourcePointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
MethodSignature signature = (MethodSignature)point.getSignature();
Method method = signature.getMethod();
DataSource ds = method.getAnnotation(DataSource.class);
if(ds == null){
//未指定数据源时,默认的数据源
DynamicDataSource.setDataSource("dataSource1");
}else{
//指定数据源时,使用指定的数据源
DynamicDataSource.setDataSource(ds.name());
}
try{
return point.proceed();
}finally{
DynamicDataSource.clearDataSource();
}
}
}
3、创建一个继承 AbstractRoutingDataSource 的类,来实现数据源的动态切换逻辑
public class DynamicDataSource extends AbstractRoutingDataSource {
// 当前使用的数据源标识
public static ThreadLocal<String> CURRENT_HOLDER = new ThreadLocal<>();
@Override
protected Object determineCurrentLookupKey() {
return getDataSource();
}
public static void setDataSource(String dataSource) {
CURRENT_HOLDER.set(dataSource);
}
public static void getDataSource() {
CURRENT_HOLDER.get();
}
public static void clearDataSource() {
CURRENT_HOLDER.remove();
}
public DynamicDataSource(DataSource defaultTargetDataSource,Map<Object,Object> targetDataSources) {
super.setTargetDataSources(targetDataSources);
// 为defaultTargetDataSource 设置默认的数据源
super.setDefaultTargetDataSource(defaultTargetDataSource);
super.afterPropertiesSet();
}
}
4、配置多数据源
@Configuration
@MapperScan(basePackages = "mapper包名",sqlSessionTemplateRef = "mySqlSessionTemplate")
public class DataSourceConfig {
/**
数据库1的配置
/
@Bean
@ConfigurationProperties(prefix = "spring.datasource.datasource1") //数据库1配置名前缀
public DataSource dataSource1() {
// 底层会自动拿到spring.datasource中的配置, 创建一个DataSource
return DataSourceBuilder.create().build();
}
/**
数据库2的配置
/
@Bean
@ConfigurationProperties(prefix = "spring.datasource.datasource2") //数据库1配置名前缀
public DataSource dataSource2() {
// 底层会自动拿到spring.datasource中的配置, 创建一个DataSource
return DataSourceBuilder.create().build();
}
@Bean(name="mysqlDataSource")
@DependsOn({"dataSource1","dataSource2"})
@Primary
public DynamicDataSource dataSource (DataSource dataSource1,DataSource dataSource2){
Map<Object,Object> targetDataSources = new HashMap<>();
targetDataSources.put("dataSource1",dataSource1);
targetDataSources.put("dataSource2",dataSource2);
return new DynamicDataSource(dataSource1,targetDataSources);
}
@Bean(name="mysqlSessionFactory")
@Primary
public SessionFactory mysqlSessionFactory(@Qualifier("mysqlDataSource") DataSource dataSource){
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
//定义分页拦截器,通过拦截 SQL 语句,动态修改查询逻辑,添加分页参数(如 LIMIT 和 OFFSET),从而简化分页代码的编写
PageInterceptor pageInterceptor = new PageInterceptor();
Properties properties = new Properties();
properties.setProperty("helperDialect","mysql");
properties.setProperty("offsetAsPageNum","true");
properties.setProperty("rowBoundsWithCount","true");
properties.setProperty("reasonable","true");
properties.setProperty("supportMethodsArguments","true");
properties.setProperty("params","pageNum=pageNum;pageSize=pageSize;");
pageInterceptor.setProperties(properties);
bean.setPlugins(pageInterceptor);
//classpath:mysql xml的路径
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mysql/*.xml"));
return bean.getObject();
}
@Bean(name="mysqlTransactionManager")
@Primary
public DataSourceTransactionManager mysqlTransactionManager(@Qualifier("mysqlDataSource") DynamicDataSource dataSource){
return new DataSourceTransactionManager(dataSource);
}
@Bean(name="mySqlSessionTemplate")
@Primary
public SqlSessionTemplate mySqlSessionTemplate(@Qualifier("mysqlSessionFactory") SqlSessionFactory sqlSessionFactory){
return new SqlSessionTemplate(sqlSessionFactory);
}
}
5、使用方法
在dao层或者impl接口上,通过@DataSource(name =“dataSource1”) 来指定查询哪个数据源
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)