mybatis plus + AOP 多數據源自動切換


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());
    }

}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM