zoukankan      html  css  js  c++  java
  • spring boot 中 Mybatis plus 多数据源的配置方法

    最近在学习spring boot,发现在jar包依赖方面做很少的工作量就可以了,对于数据库操作,我用的比较多的是mybatis plus,在中央仓库已经有mybatis-plus的插件了,对于单数据源来说直接使用就是了,但我自己的项目经常会有多数据源的情况,自己去试着写数据源的代码,核心的方法参考mp说明文档中多数据源的处理,使用动态数据源,根据需求去切换数据源

    新建spring-boot项目

    这一步大家去参考其它教程,很简单

    定义数据源相关Model

    动态数据源

    继承了抽像的数据源,并实现了DataSource,归根结底还是数据就是了,在这里面进行扩展,实现determiniCurrentlookupKey,也就是获取当前需要使用数据源的key值,在父类方法中有一个map,用来保存key值与数据源的对应关系,而key值是与当前线程相关的,DbcontextHolder代码见下

    1. package com.zhangshuo.common.dataSource;
      import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
      /**
      * Created by Administrator on 2017/5/31 0031.
      */
      publicclassDynamicDataSourceextendsAbstractRoutingDataSource{
      /**
      * 取得当前使用哪个数据源
      *
      * @return
      */
      @Override
      protectedObject determineCurrentLookupKey(){
      returnDbContextHolder.getDbType();
      }
      }

    定义DbContextHolder

    里面包含静态方法,用来设置或获取线程相关的数据源别名

    1. publicclassDbContextHolder{
      privatestaticfinalThreadLocal<String> contextHolder =newThreadLocal<>();
      /**
      * 设置数据源
      *
      * @param dbTypeEnum
      */
      publicstaticvoid setDbType(DBTypeEnum dbTypeEnum){
      contextHolder.set(dbTypeEnum.getValue());
      }
      /**
      * 取得当前数据源
      *
      * @return
      */
      publicstaticString getDbType(){
      return contextHolder.get();
      }
      /**
      * 清除上下文数据
      */
      publicstaticvoid clearDbType(){
      contextHolder.remove();
      }
      }

    定义数据源枚举类

    简化设置线程相关数据源名称的记忆压力;直接从所有的数据源的枚举中去选就可以了~

    1. publicenumDBTypeEnum{
      datasource1("datasource1"), datasource2("datasource2");
      privateString value;
      DBTypeEnum(String value){
      this.value = value;
      }
      publicString getValue(){
      return value;
      }
      }

    生成 dataource 对象及 mp需要的对象

    resources/application.properties的配置

    在这里定义的属性名要与DruidDataSource和 SqlSessionFactory中需要的属性相同,使用ConfigurationProperties注解来减少代码

    1. datasource1:
        username: root
        password: 123456
        filters: mergeStat,wall,logback
        initialSize: 5
        maxActive: 50
        minIdle: 5
        maxWait: 6000
        validationQuery: SELECT 'x'
        testOnBorrow: true
        testOnReturn: true
        testWhileIdle: true
        timeBetweenEvictionRunsMillis: 60000
        minEvictableIdleTimeMillis: 300000
        removeAbandoned: true
        removeAbandonedTimeout: 1800
        logAbandoned: true
        url: jdbc:mysql://192.168.168.118:3306/test?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&useSSL=false
      
      
      
      mybatis-plus1:
      # 数据源名称
        datasource: datasource1
        # mapper配置路径
        mapperLocations:
          classpath:/mapper/test1/*.xml
        # mybatis配置路径
        configLocation: classpath:/mybatis-config.xml
        # entity的包
        typeAliasesPackage: com.zhangshuo/test1/entity
        # 全局配置
        globalConfiguration:
          # id生成策略 0 自增 1 用户输入
          idType: 0
          # 灵据数类型
          dbType: mysql
          # 字段是否为下划线格式
          dbColumnUnderline: false
      
      datasource2:
        username: root
        password: 123456
        filters: mergeStat,wall,logback
        initialSize: 5
        maxActive: 50
        minIdle: 5
        maxWait: 6000
        validationQuery: SELECT 'x'
        testOnBorrow: true
        testOnReturn: true
        testWhileIdle: true
        timeBetweenEvictionRunsMillis: 60000
        minEvictableIdleTimeMillis: 300000
        removeAbandoned: true
        removeAbandonedTimeout: 1800
        logAbandoned: true
        url: jdbc:mysql://192.168.168.118:3306/sms?useUnicode=true&characterEncoding=utf-8
      
      mybatis-plus2:
      # 数据源名称
        datasource: datasource2
        # mapper配置路径
        mapperLocations:
          classpath:/mapper/test2/*.xml
        # mybatis配置路径
        configLocation:
        # entity的包
        typeAliasesPackage: com.zhangshuo/test2/entity
        # 全局配置
        globalConfiguration:
          # id生成策略 0 自增 1 用户输入
          idType: 0
          # 灵据数类型
          dbType: mysql
          # 字段是否为下划线格式
          dbColumnUnderline: false

    生成相应对象

    1. import com.alibaba.druid.pool.DruidDataSource;
      import com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean;
      import com.zhangshuo.common.dataSource.DynamicDataSource;
      import org.mybatis.spring.annotation.MapperScan;
      import org.springframework.beans.factory.annotation.Qualifier;
      import org.springframework.boot.context.properties.ConfigurationProperties;
      import org.springframework.boot.context.properties.ConfigurationPropertiesBinding;
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      import org.springframework.context.annotation.Primary;
      import javax.sql.DataSource;
      import java.util.Map;
      import java.sql.SQLException;
      import java.util.HashMap;
      /**
      * Created by Administrator on 2017/5/31 0031.
      */
      @Configuration
      @MapperScan(value ={"com.zhangshuo.test1.mapper","com.zhangshuo.test2.mapper"})
      publicclassDataSourceConfig{
      @ConfigurationProperties(prefix ="datasource1")
      @Bean(name ="datasource1")
      // @Primary
      /**
      * 在方法上注解configurationProperties时,将会把属性注入到返回结果的bean中
      */
      publicDruidDataSource dataSource1()throwsSQLException{
      returnnewDruidDataSource();
      }
      @ConfigurationProperties(prefix ="datasource2")
      @Bean(name ="datasource2")
      /**
      * 在方法上注解configurationProperties时,将会把属性注入到返回结果的bean中
      */
      publicDruidDataSource dataSource2()throwsSQLException{
      returnnewDruidDataSource();
      }
      @Bean(name ="datasource")
      @Primary
      publicDynamicDataSource dynamicDataSource(@Qualifier(value ="datasource1")DataSource dataSource1,@Qualifier(value ="datasource2")DataSource dataSource2){
      DynamicDataSource bean =newDynamicDataSource();
      Map<Object,Object> targetDataSources =newHashMap<>();
      targetDataSources.put("datasource1",dataSource1);
      targetDataSources.put("datasource2", dataSource2);
      bean.setTargetDataSources(targetDataSources);
      bean.setDefaultTargetDataSource(dataSource1);
      return bean;
      }
      @Bean(name ="sessionFactory1")
      @ConfigurationProperties(prefix ="mybatis-plus1")
      @ConfigurationPropertiesBinding()
      @Primary
      publicMybatisSqlSessionFactoryBean sqlSessionFactory1(@Qualifier(value ="datasource")DataSource dataSource){
      MybatisSqlSessionFactoryBean bean =newMybatisSqlSessionFactoryBean();
      bean.setDataSource(dataSource);
      return bean;
      }
      @Bean(name ="sessionFactory2")
      @ConfigurationProperties(prefix ="mybatis-plus2")
      @ConfigurationPropertiesBinding()
      publicMybatisSqlSessionFactoryBean sqlSessionFactory2(@Qualifier(value ="datasource")DataSource dataSource){
      MybatisSqlSessionFactoryBean bean =newMybatisSqlSessionFactoryBean();
      bean.setDataSource(dataSource);
      return bean;
      }
      }

    设置AOP用来自动切换数据源

    在这里说明下我的目录结构:
    com.zhangshuo.test1.controller/service/mapper
    com.zhangshuo.test2.controller/service/mapper

    设置AOP

    在dao层进行切换

    1. import com.zhangshuo.common.dataSource.DBTypeEnum;
      import com.zhangshuo.common.dataSource.DbContextHolder;
      import org.aspectj.lang.annotation.Aspect;
      import org.aspectj.lang.annotation.Before;
      import org.aspectj.lang.annotation.Pointcut;
      import org.slf4j.Logger;
      import org.slf4j.LoggerFactory;
      import org.springframework.stereotype.Component;
      /**
      * Created by Administrator on 2017/5/31 0031.
      * 以dao层进行切换
      */
      @Component
      @Aspect
      publicclassDataSourceInterceptor{
      Logger logger =LoggerFactory.getLogger(DataSourceInterceptor.class);
      @Pointcut(value ="execution(public * com.zhangshuo.test1.mapper.**.*(..))")
      privatevoid datasource1ServicePointcut(){};
      @Pointcut(value ="execution(public * com.zhangshuo.test2.mapper.**.*(..))")
      privatevoid datasource2ServicePointcut(){};
      /**
      * 切换数据源1
      */
      @Before("datasource1ServicePointcut()")
      publicvoid dataSource1Interceptor(){
      logger.debug("切换到数据源{}..............................","datasource1");
      DbContextHolder.setDbType(DBTypeEnum.datasource1);
      }
      /**
      * 切换数据源2
      */
      @Before("datasource2ServicePointcut()")
      publicvoid dataSource2Interceptor(){
      logger.debug("切换到数据源{}.......................","datasource2");
      DbContextHolder.setDbType(DBTypeEnum.datasource2);
      }
      }

    到这里就可以进行测试了;
    顺带贴下mybatis-plus的分页插件,我是定义到了mybatis-config.xml中,也可以手动在sqlSessionfacotry中的setPlugins中()定义;

    1. <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE configuration
              PUBLIC "-//ibatis.apache.org//DTD Config 3.0//EN"
              "http://ibatis.apache.org/dtd/ibatis-3-config.dtd">
      
      <configuration>
          <settings>
              <setting name="cacheEnabled" value="false"/>
              <setting name="lazyLoadingEnabled" value="false"/>
              <setting name="aggressiveLazyLoading" value="true"/>
              <setting name="logImpl" value="slf4j"/>
          </settings>
          <plugins>
              <plugin interceptor="com.baomidou.mybatisplus.plugins.PaginationInterceptor">
                  <property name="dialectType" value="mysql" />
                  <property name="optimizeType" value="aliDruid" />
              </plugin>
          </plugins>
      </configuration>
  • 相关阅读:
    (PHP)redis Zset(有序集合 sorted set)操作
    (PHP)redis Set(集合)操作
    (PHP)redis Hash(哈希)操作
    (PHP)redis String(字符串)操作
    (PHP)redis List(列表)操作
    PHP连接 redis
    PHP json 对象 数组互相转换
    循环节长度 蓝桥杯
    三羊献瑞 蓝桥杯
    立方变自身
  • 原文地址:https://www.cnblogs.com/417xiaoliu/p/6924901.html
Copyright © 2011-2022 走看看