SpringBootプロジェクトでの複数のデータソース構成

AOP を介して Mybatis マルチデータ ソース スイッチングを実現します。

yml ファイル構成:

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #打印mybatis sql日志
spring:
  datasource:
    druid:
      master-db:
        url: jdbc:mysql://120.0.0.1:3306/sydtjc
        username: root
        password: root
      mysql-db:
        url: jdbc:mysql://120.0.0.1:3306/ggfw
        username: root
        password: root
      bjggfw-db:
        url: jdbc:mysql://120.0.0.1:3306/ggfw_ggfw
        username: root
        password: root

カスタム注釈

import java.lang.annotation.*;

@Documented
@Target({
    
    ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSourceAnnotation {
    
    
    DBTypeEnum value() default DBTypeEnum.Master;
}

カスタムタイプ:

public enum DBTypeEnum {
    
    

    Master("master"), Oracle("oracle"), Mysql("mysql"), Bjggfw("bjggfw");

    private String value;

    DBTypeEnum(String value) {
    
    
        this.value = value;
    }

    public String getValue() {
    
    
        return value;
    }
}

パブリックメソッド:

public class DbContextHolder {
    
    
    public static final DBTypeEnum DEFAULT_DATA_SOURCE = DBTypeEnum.Master;
    private static final ThreadLocal<DBTypeEnum> CONTEXT_HOLDER = new ThreadLocal<>();

    static {
    
    
        setDefaultDataSource(); // 默认指定master
    }

    /**
     * 设置默认数据源
     */
    public static void setDefaultDataSource() {
    
    
        CONTEXT_HOLDER.set(DEFAULT_DATA_SOURCE);
    }

    /**
     * 取得当前数据源
     *
     * @return
     */
    public static DBTypeEnum getDbType() {
    
    
        return CONTEXT_HOLDER.get();
    }

    /**
     * 设置数据源
     *
     * @param dbTypeEnum
     */
    public static void setDbType(DBTypeEnum dbTypeEnum) {
    
    
        CONTEXT_HOLDER.set(dbTypeEnum);
    }

    /**
     * 清除上下文数据
     */
    public static void clearDbType() {
    
    
        CONTEXT_HOLDER.remove();
    }
}

セクションクラス:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Aspect
@Component
public class DynamicDataSourceAspect {
    
    

    @Around("@within(com.ylz.bjyf.common.multipledatasource.DataSourceAnnotation) || @annotation(com.ylz.bjyf.common.multipledatasource.DataSourceAnnotation)")
    public Object before(ProceedingJoinPoint point) throws Throwable {
    
    
        Class<?> clazz = point.getTarget().getClass();
        MethodSignature signature = (MethodSignature) point.getSignature();
        try {
    
    
            if (clazz.isAnnotationPresent(DataSourceAnnotation.class)) {
    
    
                DataSourceAnnotation annotation = clazz.getAnnotation(DataSourceAnnotation.class);
                DbContextHolder.setDbType(annotation.value());
            }
            Method method = clazz.getMethod(signature.getName(), signature.getParameterTypes());
            if (method.isAnnotationPresent(DataSourceAnnotation.class)) {
    
    
                // 根据注解设置数据源
                DataSourceAnnotation annotation = method.getAnnotation(DataSourceAnnotation.class);
                DbContextHolder.setDbType(annotation.value());
            }
            return point.proceed();
        } catch (Exception e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            DbContextHolder.setDbType(DBTypeEnum.Master);
        }
        return null;
    }

}

複数のデータ ソース構成クラス:

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class DynamicDataSource extends AbstractRoutingDataSource {
    
    
    /**
     * 取得当前使用哪个数据源
     *
     * @return
     */
    @Override
    protected Object determineCurrentLookupKey() {
    
    
        return DbContextHolder.getDbType();
    }
}

構成クラス:

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.ylz.bjyf.common.multipledatasource.DBTypeEnum;
import com.ylz.bjyf.common.multipledatasource.DynamicDataSource;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

@EnableTransactionManagement
@Configuration
@MapperScan({
    
     "org.mohrss.leaf.**.entity", "com.ylz.bjyf.**.mapper" }) // 注意,不要扫描jpa接口,否则使用jpa时会出现问题
public class MybatisPlusConfig {
    
    

   /**
    * 分页插件
    */
   @Bean
   public PaginationInterceptor paginationInterceptor() {
    
    
      return new PaginationInterceptor();
   }

   @Bean(name = "masterDb")
   @ConfigurationProperties(prefix = "spring.datasource.druid.master-db")
   public DataSource masterDb() {
    
    
      return DruidDataSourceBuilder.create().build();
   }

   @Bean(name = "mysqlDb")
   @ConfigurationProperties(prefix = "spring.datasource.druid.mysql-db")
   public DataSource mysqlDb() {
    
    
      return DruidDataSourceBuilder.create().build();
   }

   @Bean(name = "bjggfwDb")
   @ConfigurationProperties(prefix = "spring.datasource.druid.bjggfw-db")
   public DataSource bjggfwDb() {
    
    
      return DruidDataSourceBuilder.create().build();
   }


   /**
    * 动态数据源配置
    *
    * @return
    */
   @Bean
   @Primary
   public DynamicDataSource dynamicDataSource(@Qualifier("masterDb") DataSource masterDb,
                                    @Qualifier("mysqlDb") DataSource mysqlDb,
                                    @Qualifier("bjggfwDb") DataSource bjggfwDb) {
    
    
      DynamicDataSource dynamicDataSource = new DynamicDataSource();
      Map<Object, Object> targetDataSources = new HashMap<>(2);
      targetDataSources.put(DBTypeEnum.Master, masterDb);
      targetDataSources.put(DBTypeEnum.Mysql, mysqlDb);
      targetDataSources.put(DBTypeEnum.Bjggfw, bjggfwDb);
      dynamicDataSource.setTargetDataSources(targetDataSources);
      dynamicDataSource.setDefaultTargetDataSource(masterDb);
      return dynamicDataSource;
   }

   @Bean("sqlSessionFactory")
   public SqlSessionFactory sqlSessionFactory(DynamicDataSource dynamicDataSource) throws Exception {
    
    
      MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
      sqlSessionFactory.setDataSource(dynamicDataSource);
      // sqlSessionFactory.setMapperLocations(new
      // PathMatchingResourcePatternResolver().getResources("classpath:/mapper/*/*Mapper.xml"));

      MybatisConfiguration configuration = new MybatisConfiguration();
      // configuration.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class);
      configuration.setJdbcTypeForNull(JdbcType.NULL);
      configuration.setMapUnderscoreToCamelCase(true);
      configuration.setCacheEnabled(false);
      sqlSessionFactory.setConfiguration(configuration);
      sqlSessionFactory.setPlugins(new Interceptor[]{
    
     // performanceInterceptor(),OptimisticLockerInterceptor()
            paginationInterceptor() // 添加分页功能
      });
//        sqlSessionFactory.setGlobalConfig(globalConfiguration());
      return sqlSessionFactory.getObject();
   }
}

おすすめ

転載: blog.csdn.net/m0_46459413/article/details/130249036