zoukankan      html  css  js  c++  java
  • springboot+druid+mybatis plus的多数据源配置

    思路

    1. yml中配置多个数据源信息
    2. 通过AOP切换不同数据源
    3. 配合mybatis plus使用

    POM依赖

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <!-- AOP依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.0.0</version>
    </dependency>
    <!-- MyBatisPlus -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.1.0</version>
    </dependency>
    <!--Mysql-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.6</version>
        <scope>runtime</scope>
    </dependency>
    <!-- Druid依赖 -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>1.1.10</version>
    </dependency>

    YML配置

    spring:
      aop:
        proxy-target-class: true
        auto: true
      datasource:
        druid:
          es:
            url: jdbc:mysql://192.168.21.181:3306/jarvis
            username: root
            password: 123456
            type: com.alibaba.druid.pool.DruidDataSource
            driver-class-name: com.mysql.jdbc.Driver
            initialSize: 5
            minIdle: 5
            maxActive: 20
          wx:
            initialSize: 5
            minIdle: 5
            maxActive: 20
            type: com.alibaba.druid.pool.DruidDataSource
            driver-class-name: com.mysql.jdbc.Driver
            username: root
            password: 123456
            url: jdbc:mysql://192.168.21.181:3306/jarvis_wx

    启动加载多个数据源

    package com.jarvis.config;
    
    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.plugins.PerformanceInterceptor;
    import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
    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;
    
    @Configuration
    @EnableTransactionManagement
    @MapperScan("com.jarvis.task.*.mapper")
    public class MybatisPlusConfig {
    
        /***
         * plus 的性能优化
         */
        @Bean
        public PerformanceInterceptor performanceInterceptor() {
            PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
            /* <!-- SQL 执行性能分析,开发环境使用,线上不推荐。 maxTime 指的是 sql 最大执行时长 --> */
            //performanceInterceptor.setMaxTime(1000);
            /* <!--SQL是否格式化 默认false--> */
            performanceInterceptor.setFormat(false);
            return performanceInterceptor;
        }
    
        /**
         * mybatis-plus 分页插件
         */
        @Bean
        public PaginationInterceptor paginationInterceptor() {
            PaginationInterceptor page = new PaginationInterceptor();
            page.setDialectType("mysql");
            return page;
        }
    
    
        @Bean(name = "esDb")
        @ConfigurationProperties(prefix = "spring.datasource.druid.es" )
        public DataSource esDb () {
            return DruidDataSourceBuilder.create().build();
        }
    
        @Bean(name = "wxDb")
        @ConfigurationProperties(prefix = "spring.datasource.druid.wx" )
        public DataSource wxDb () {
            return DruidDataSourceBuilder.create().build();
        }
        /**
         * 动态数据源配置
         * @return
         */
        @Bean
        @Primary
        public DataSource multipleDataSource (@Qualifier("esDb") DataSource esDb,
                                              @Qualifier("wxDb") DataSource wxDb ) {
            DynamicDataSource dynamicDataSource = new DynamicDataSource();
            Map< Object, Object > targetDataSources = new HashMap<>(2);
            targetDataSources.put(DBTypeEnum.ES.getValue(), esDb );
            targetDataSources.put(DBTypeEnum.WX.getValue(), wxDb);
            dynamicDataSource.setTargetDataSources(targetDataSources);
            dynamicDataSource.setDefaultTargetDataSource(esDb);
            return dynamicDataSource;
        }
    
        @Bean("sqlSessionFactory")
        public SqlSessionFactory sqlSessionFactory() throws Exception {
            MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
            sqlSessionFactory.setDataSource(multipleDataSource(esDb(),wxDb()));
            //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();
        }
    
    //    @Bean
    //    public GlobalConfiguration globalConfiguration() {
    //        GlobalConfiguration conf = new GlobalConfiguration(new LogicSqlInjector());
    //        conf.setLogicDeleteValue("-1");
    //        conf.setLogicNotDeleteValue("1");
    //        conf.setIdType(0);
    //        conf.setMetaObjectHandler(new MyMetaObjectHandler());
    //        conf.setDbColumnUnderline(true);
    //        conf.setRefresh(true);
    //        return conf;
    //    }
    }

    DBType枚举类

    public enum DBTypeEnum {
        ES("es"), WX("wx");
        private String value;
    
        DBTypeEnum(String value) {
            this.value = value;
        }
    
        public String getValue() {
            return value;
        }
    }

    动态数据源决策

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

    设置、获取数据源

    public class DbContextHolder {
        private static final ThreadLocal contextHolder = new ThreadLocal<>();
        /**
         * 设置数据源
         * @param dbTypeEnum
         */
        public static void setDbType(DBTypeEnum dbTypeEnum) {
            contextHolder.set(dbTypeEnum.getValue());
        }
    
        /**
         * 取得当前数据源
         * @return
         */
        public static String getDbType() {
            return (String) contextHolder.get();
        }
    
        /**
         * 清除上下文数据
         */
        public static void clearDbType() {
            contextHolder.remove();
        }
    }

    AOP实现的数据源切换

    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 DataSourceSwitchAspect {
    
        @Pointcut("execution(* com.jarvis.task.db2es.mapper..*.*(..))")
        private void jarvisAspect() {
        }
    
        @Pointcut("execution(* com.jarvis.task.dt2db.mapper..*.*(..))")
        private void jarvisWxAspect() {
        }
    
        @Before("jarvisAspect()")
        public void jarvisDb() {
            log.info("切换到ES 数据源...");
            DbContextHolder.setDbType(DBTypeEnum.ES);
        }
    
        @Before("jarvisWxAspect()")
        public void jarvisWxDb () {
            log.info("切换到WX 数据源...");
            DbContextHolder.setDbType(DBTypeEnum.WX);
        }
    }

    mapper层结构

     参考

      https://www.jianshu.com/p/ff5af6c59365?utm_source=oschina-app

  • 相关阅读:
    LeetCode对撞指针汇总
    167. Two Sum II
    215. Kth Largest Element in an Array
    2018Action Recognition from Skeleton Data via Analogical Generalization over Qualitative Representations
    题解 Educational Codeforces Round 84 (Rated for Div. 2) (CF1327)
    题解 JZPKIL
    题解 八省联考2018 / 九省联考2018
    题解 六省联考2017
    题解 Codeforces Round #621 (Div. 1 + Div. 2) (CF1307)
    题解Codeforces Round #620 (Div. 2)
  • 原文地址:https://www.cnblogs.com/szwdun/p/11263201.html
Copyright © 2011-2022 走看看