1. 程式人生 > 其它 >使用springboot + druid + mybatisplus完成多資料來源配置

使用springboot + druid + mybatisplus完成多資料來源配置

最近專案中需要使用多個數據源完成業務,經過多方尋找資料和親自測試,現在整理一下資料。本文參考:https://www.cnblogs.com/hsbt2333/p/9347249.html

1.在yml中配置多個數據源訪問連線

server:
  port: 8099
#配置資料來源的屬性
spring:
  datasource:
    druid:
      db1:
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/standarddb?useUnicode=true&characterEncoding=utf8&nullCatalogMeansCurrent=true&useSSL=false&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
username: root password: ******** db2: url: jdbc:mysql://IP:3306/rebiaoserver?useUnicode=true&characterEncoding=UTF-8&useSSL=false&allowMultiQueries=true&rewriteBatchedStatements=true username: root password: ******** driver-class-name: com.mysql.cj.jdbc.Driver #監控配置 stat
-view-servlet: enabled: true login-username: root login-password: roo #thymeleaf的配置 thymeleaf: cache: false enabled: true #設定開發環境 profiles: active: dev #時區轉換 jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8 #redis redis: database:
0 host: 127.0.0.1 #password: 123 port: 6379 timeout: 3000 # 連線超時時間 單位 ms(毫秒) # cluster: # nodes: 10.3.1.4:7000,10.3.1.4:7001,...,10.3.1.4:7008 #配置mybatisplus mybatis-plus: mapper-locations: - classpath:mapper/*/*Mapper.xml global-config: db-config: id-type: auto logic-delete-value: 1 logic-not-delete-value: 0 banner: true configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 分頁外掛 pagehelper: helperDialect: mysql reasonable: true supportMethodsArguments: true params: count=countSql

2. 建立資料來源列舉類DataSourceEnum

package com.ckfuture.pro.DBSource;
/**
 * @description: 多資料來源列舉
 * @author: CKFuture
 * @since: 2021-11-09 13:33
 * @version: v1.0
 * @LastEditTime:
 * @LastEditors:
 * @copyright: hrbckfuture.com
 */
public enum DataSourceEnum {
    DB1("db1"),DB2("db2");

    private String value;

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

    public String getValue() {
        return value;
    }
}

3. 建立DataSourceContextHolder類

package com.ckfuture.pro.DBSource;


public class DataSourceContextHolder {
    private static final ThreadLocal<String> contextHolder = new InheritableThreadLocal<>();

    /**
     *  設定資料來源
     * @param db
     */
    public static void setDataSource(String db){
        contextHolder.set(db);
    }

    /**
     * 取得當前資料來源
     * @return
     */
    public static String getDataSource(){
        return contextHolder.get();
    }

    /**
     * 清除上下文資料
     */
    public static void clear(){
        contextHolder.remove();
    }
}

4. 建立MultipleDataSource類

package com.ckfuture.pro.DBSource;

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

public class MultipleDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDataSource();
    }
}

5.建立DataSource註解

package com.ckfuture.pro.annotation;


import com.ckfuture.pro.DBSource.DataSourceEnum;

import java.lang.annotation.*;
/**
 * @description: DataSource註解
 * @author: CKFuture
 * @since: 2021-11-09 13:35
 * @version: v1.0
 * @LastEditTime:
 * @LastEditors:
 * @copyright: hrbckfuture.com
 */
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {

    DataSourceEnum value() default DataSourceEnum.DB1;
}

6.建立DataSourceAspect類

package com.ckfuture.pro.DBSource;

import com.ckfuture.pro.annotation.DataSource;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;


@Component
@Slf4j
@Aspect
@Order(-1)
public class DataSourceAspect {

    @Pointcut("@within(com.ckfuture.pro.annotation.DataSource) || @annotation(com.ckfuture.pro.annotation.DataSource)")
    public void pointCut(){

    }

    @Before("pointCut() && @annotation(dataSource)")
    public void doBefore(DataSource dataSource){
        log.info("選擇資料來源---"+dataSource.value().getValue());
        DataSourceContextHolder.setDataSource(dataSource.value().getValue());
    }

    @After("pointCut()")
    public void doAfter(){
        DataSourceContextHolder.clear();
    }
}

7.建立配置類MyBatiesPlusConfiguration

package com.ckfuture.pro.config;

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
/*import com.baomidou.mybatisplus.MybatisConfiguration;
import com.baomidou.mybatisplus.entity.GlobalConfiguration;
import com.baomidou.mybatisplus.mapper.LogicSqlInjector;
import com.baomidou.mybatisplus.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.plugins.PerformanceInterceptor;
import com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean;*/

import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.ckfuture.pro.DBSource.DataSourceEnum;
import com.ckfuture.pro.DBSource.MultipleDataSource;
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.context.annotation.Profile;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Configuration
@MapperScan("com.ckfuture.pro.*.*.dao")
public class MyBatiesPlusConfiguration {


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

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

    /**
     * 動態資料來源配置
     * @return
     */
    @Bean
    @Primary
    public DataSource multipleDataSource(@Qualifier("db1") DataSource db1, @Qualifier("db2") DataSource db2) {
        MultipleDataSource multipleDataSource = new MultipleDataSource();
        Map< Object, Object > targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceEnum.DB1.getValue(), db1);
        targetDataSources.put(DataSourceEnum.DB2.getValue(), db2);
        //新增資料來源
        multipleDataSource.setTargetDataSources(targetDataSources);
        //設定預設資料來源
        multipleDataSource.setDefaultTargetDataSource(db1);
        return multipleDataSource;
    }
}

8.使用資料來源1

只需要在服務實現類的方法上添加註解@DataSource(DataSourceEnum.DB1)即可。

9.使用資料來源2

只需要在服務實現類的方法上添加註解@DataSource(DataSourceEnum.DB2)即可。

這裡本人拋磚引玉,個人建議還是儘量不要在springboot中使用多資料來源,第一是比較麻煩,第二是不安全,還是建議使用springcloud。