springboot 动态多数据源
应用:同一个应用中使用多个数据库,根据需要切换数据库
*********************
相关类与接口
AbstractRoutingDataSource
public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean {
************
部分字段
@Nullable
private Map<Object, Object> targetDataSources; //目标数据源
@Nullable
private Object defaultTargetDataSource; //默认数据源
************
常用方法
public void setTargetDataSources(Map<Object, Object> targetDataSources) {
this.targetDataSources = targetDataSources;
} //设置目标数据源
public void setDefaultTargetDataSource(Object defaultTargetDataSource) {
this.defaultTargetDataSource = defaultTargetDataSource;
} //设置默认数据源
@Nullable
protected abstract Object determineCurrentLookupKey();
//抽象方法,设置数据源的key
*********************
示例:同一应用中向不同的数据库中插入数据
数据库h1:表user
数据库h2:表person
******************
config 层
DynamicDatasource:动态数据源切换
public class DynamicDataSource extends AbstractRoutingDataSource {
private ThreadLocal<DataSource_Enum> threadLocal=new ThreadLocal<>();
public void switchDataSource(DataSource_Enum dataSource_enum){
threadLocal.set(dataSource_enum);
}
@Override
protected Object determineCurrentLookupKey() {
return threadLocal.get();
}
DataConfig:配置数据源
@Configuration
@EnableAspectJAutoProxy
@MapperScan("com.example.demo.dao")
public class DataConfig {
@Bean("one")
@ConfigurationProperties("spring.datasource.druid.one")
public DataSource initOneDataSource(){
return DruidDataSourceBuilder.create().build();
}
@Bean("two")
@ConfigurationProperties("spring.datasource.druid.two")
public DataSource initSecondDataSource(){
return DruidDataSourceBuilder.create().build();
}
@Bean
@Primary
public DynamicDataSource initDynamicDataSource(@Qualifier("one") DataSource ds1, @Qualifier("two") DataSource ds2){
DynamicDataSource dynamicDataSource=new DynamicDataSource();
Map<Object,Object> map=new HashMap<>();
map.put(DataSource_Enum.one,ds1);
map.put(DataSource_Enum.two,ds2);
dynamicDataSource.setTargetDataSources(map);
dynamicDataSource.setDefaultTargetDataSource(ds1);
return dynamicDataSource;
}
DataSource_Enum
public enum DataSource_Enum{
one,two
}
*********************
aop 层
CustomAspect
@Aspect
@Component
public class CustomAspect {
@Resource
private DynamicDataSource dataSource;
@Pointcut("execution(* *..UserMapper.*(..))")
public void funOne(){
}
@Pointcut("execution(* *..PersonMapper.*(..))")
public void funTwo(){
}
@Before("funOne()")
public void beforeOne(){ //使用UserMapper时,使用数据库:one
dataSource.switchDataSource(DataSource_Enum.one);
}
@Before("funTwo()")
public void beforeTwo(){ //使用PersonMapper时,使用数据库:two
dataSource.switchDataSource(DataSource_Enum.two);
}
}
*********************
controller 层
UserController
@RestController
@RequestMapping("/user")
public class UserController {
@Resource
private UserMapper userMapper;
@RequestMapping("/save")
public String save(){
for (int i=0;i<10;i++){
User user=new User();
user.setName("瓜田李下 "+i);
user.setAge(i%5+10);
userMapper.insert(user);
}
return "success";
}
}
PersonController
@RestController
@RequestMapping("/person")
public class PersonController {
@Resource
private PersonMapper personMapper;
@RequestMapping("/save")
public String save(){
for (int i=0;i<10;i++){
Person person=new Person();
person.setName("海贼王 "+i);
person.setAge(i%4+12);
personMapper.insert(person);
}
return "success";
}
}
*********************
插入数据测试
表 user
表 person