- 實現功能爲通 aop 控制不同包下面的類採用不同的數據庫
- 在
mapper.one
包中的數據庫採用one_db
- 在
mapper.two
包總的數據庫採用two_db
- 在
導入相關依賴
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.21</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
在配置文件中配置數據源
##onedb
spring.datasource.druid.one.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.druid.one.url=jdbc:mysql://localhost:3306/db_one?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
spring.datasource.druid.one.username=username
spring.datasource.druid.one.password=password
##twodb
spring.datasource.druid.two.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.druid.two.url=jdbc:mysql://localhost:3306/db_two?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
spring.datasource.druid.two.username=username
spring.datasource.druid.two.password=password
配置 MyBatisPlus 相關
mybatis-plus:
mapper-locations: classpath:/mapper/**/*Mapper.xml
typeAliasesPackage: com.sec.datasource.*.domain
global-config:
refresh: true
db-config:
id-type: auto
field-strategy: ignored
capital-mode: true
logic-delete-value: 1
logic-not-delete-value: 0
db-type: mysql
configuration:
map-underscore-to-camel-case: true
cache-enabled: false
jdbc-type-for-null: 'null'
在
config
包下配置 MyBatisPlus 數據源
@Configuration
@MapperScan("com.sec.datasource.datasource.mapper")
public class MyBatiesPlusConfiguration {
@Bean(name = "one")
@ConfigurationProperties(prefix = "spring.datasource.druid.one" )
public DataSource one() {
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "two")
@ConfigurationProperties(prefix = "spring.datasource.druid.two" )
public DataSource two() {
return DruidDataSourceBuilder.create().build();
}
/**
* 動態數據源配置
* @return
*/
@Bean
@Primary
public DataSource multipleDataSource(@Qualifier("one") DataSource onedb, @Qualifier("two") DataSource twodb) {
MultipleDataSource multipleDataSource = new MultipleDataSource();
Map< Object, Object > targetDataSources = new HashMap<>();
targetDataSources.put(DataSourceEnum.ONE_DB.getValue(), onedb);
targetDataSources.put(DataSourceEnum.TWO_DB.getValue(), twodb);
//添加數據源
multipleDataSource.setTargetDataSources(targetDataSources);
//設置默認數據源
multipleDataSource.setDefaultTargetDataSource(onedb);
return multipleDataSource;
}
@Bean("sqlSessionFactory")
public SqlSessionFactory sqlSessionFactory() throws Exception {
MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
sqlSessionFactory.setDataSource(multipleDataSource(one(), two()));
MybatisConfiguration configuration = new MybatisConfiguration();
configuration.setJdbcTypeForNull(JdbcType.NULL);
configuration.setMapUnderscoreToCamelCase(true);
configuration.setCacheEnabled(false);
sqlSessionFactory.setConfiguration(configuration);
return sqlSessionFactory.getObject();
}
}
其他輔助類
public class DataSourceContextHolder {
private static final ThreadLocal<String> contextHolder = new InheritableThreadLocal<>();
public static void setDataSource(DataSourceEnum db){
contextHolder.set(db.getValue());
}
public static String getDataSource(){
return contextHolder.get();
}
public static void clear(){
contextHolder.remove();
}
}
public class MultipleDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDataSource();
}
}
將已有數據庫定義成枚舉方便調用
@Getter
public enum DataSourceEnum {
ONE_DB("one_db"),
TWO_DB("two_db");
private String value;
DataSourceEnum(String value){this.value=value;}
}
編寫 aop 邏輯進行數據源切換
@Slf4j
@Aspect
@Order(-1)
@Component
public class DataSourceAspect {
@Pointcut("execution(* com.sec.datasource.datasource.mapper.onedb.*.*(..))")
private void onedbAspect() {
}
@Pointcut("execution(* com.sec.datasource.datasource.mapper.twodb.*.*(..))")
private void twodbAspect() {
}
@Before("onedbAspect()")
public void onedb() {
log.info("select to datasource one");
DataSourceContextHolder.setDataSource(DataSourceEnum.ONE_DB);
}
@Before("twodbAspect()")
public void twodb() {
log.info("select to datasource two");
DataSourceContextHolder.setDataSource(DataSourceEnum.TWO_DB);
}
@After("onedbAspect() || twodbAspect()")
public void doAfter(){
DataSourceContextHolder.clear();
}
}
下面就是在 mapper 包中編寫邏輯 controller 調用測試了
Demo 在我的 Gitee 中可以看得到
https://gitee.com/jiangruyi/many-datasource.git