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: psw
2. 數據源枚舉類
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()); } }