mituan 2020-05-26
1. 数据库配置
# .yml 文件
spring:
datasource:
db1:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc-url # 配置
username: root
password: psw
db2:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc-url # 配置
username: root
password: psw2. 数据源枚举类
public enum DataSourceEnums {
PRIMARY("primaryDataSource"),
SECOND("secondDataSource");
private String value;
DataSourceEnums(String value){this.value=value;}
public String getValue() {
return value;
}
}3. mybatis plus Config 数据源切换类
@Configuration
@MapperScan(value = {"com.example.demo.dao"})
public class MybatisPlusConfig {
@Bean(name = "primaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.db1")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "secondDataSource")
@ConfigurationProperties(prefix = "spring.datasource.db2")
public DataSource secondDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "multipleTransactionManager")
@Primary
public DataSourceTransactionManager multipleTransactionManager(@Qualifier("multipleDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
/**
* 动态数据源配置
*/
@Bean(name = "multipleDataSource")
@Primary
public DataSource multipleDataSource(@Qualifier("primaryDataSource") DataSource primaryDataSource,
@Qualifier("secondDataSource") DataSource secondDataSource) {
DataSourceContextHolder dynamicDataSource = new DataSourceContextHolder();
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DataSourceEnums.PRIMARY.getValue(), primaryDataSource);
targetDataSources.put(DataSourceEnums.SECOND.getValue(), secondDataSource);
dynamicDataSource.setTargetDataSources(targetDataSources);
dynamicDataSource.setDefaultTargetDataSource(secondDataSource); // 程序默认数据源,这个要根据程序调用数据源频次,经常把常调用的数据源作为默认
return dynamicDataSource;
}
@Bean("sqlSessionFactory")
public SqlSessionFactory sqlSessionFactory() throws Exception {
MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
sqlSessionFactory.setDataSource(multipleDataSource(primaryDataSource(), secondDataSource()));
MybatisConfiguration configuration = new MybatisConfiguration();
configuration.setJdbcTypeForNull(JdbcType.NULL);
//是否使用转驼峰
configuration.setMapUnderscoreToCamelCase(true);
configuration.setCacheEnabled(false);
sqlSessionFactory.setConfiguration(configuration);//扫描 mapper 路径
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resource = resolver.getResources("classpath:mapper/**/*.xml");
sqlSessionFactory.setMapperLocations(resource);
return sqlSessionFactory.getObject();
}
}3. DataSource 数据源获取类
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
@Slf4j
public class DataSourceContextHolder extends AbstractRoutingDataSource {
public static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
/**
* 获取数据源
*/
@Override
protected Object determineCurrentLookupKey() {
log.info("当前选择的数据源是:" + contextHolder.get());
return contextHolder.get();
}
/**
* 设置数据源*/
public static void setDataSource(String db){
contextHolder.set(db);
}
/**
* 取得当前数据源
* @return
*/
public static String getDataSource(){
return contextHolder.get();
}
/**
* 清除上下文数据
*/
public static void clear(){
contextHolder.remove();
}
}4. AOP切面
import com.example.demo.config.DataSourceContextHolder;
import com.example.demo.enums.DataSourceEnums;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Aspect
@Order(-100) //这是为了保证AOP在事务注解之前生效,Order的值越小,优先级越高
@Slf4j
public class AOP {
/**
* mybatis plus 动态切换数据源
* */
// 定义切点
@Before("execution(* com.example.demo.dao.db1..*(..))")
public void db1() {
log.info("数据源切换到db1...");
DataSourceContextHolder.setDataSource(DataSourceEnums.PRIMARY.getValue());
}
@Before("execution(* com.example.demo.dao.db2..*(..))")
public void db2() {
log.info("数据源切换到db2...");
DataSourceContextHolder.setDataSource(DataSourceEnums.SECOND.getValue());
}
}