SpringBoot多數據源配置



最近項目用到了 spring多數據源配置,恰好看到這篇好文章,特地分享下
點擊了解Spring多數據源XML配置

1 SpringBoot分庫配置

主要介紹兩種整合方式,分別是 springboot+mybatis 使用分包方式整合,和 springboot+druid+mybatisplus 使用注解方式整合

1.1 准備數據

在本地新建兩個數據庫,名稱分別為db1db2,新建一張user表,表結構如下
在這里插入圖片描述

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  `name` varchar(25) NOT NULL COMMENT '姓名',
  `age` int(2) DEFAULT NULL COMMENT '年齡',
  `sex` tinyint(1) NOT NULL DEFAULT '0' COMMENT '性別:0-男,1-女',
  `addr` varchar(100) DEFAULT NULL COMMENT '地址',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='測試用戶表'

1.2 springboot+mybatis使用分包方式整合

1.2.1 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.9.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>multipledatasource</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>multipledatasource</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>
   
    <dependencies>
        <!-- spring 依賴 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
         <!-- mysql 依賴 -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.0</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

1.2.2 application.yml 配置文件

server:
  port: 8080 # 啟動端口
spring:
  datasource: 
    db1: # 數據源1
      jdbc-url: jdbc:mysql://localhost:3306/db1?characterEncoding=utf8&useUnicode=true&useSSL=false&serverTimezone=GMT%2B8
      username: root
      password: root
      driver-class-name: com.mysql.cj.jdbc.Driver
    db2: # 數據源2
      jdbc-url: jdbc:mysql://localhost:3306/db2?characterEncoding=utf8&useUnicode=true&useSSL=false&serverTimezone=GMT%2B8
      username: root
      password: root
      driver-class-name: com.mysql.cj.jdbc.Driver

注意事項:
各個版本的 springboot 配置 datasource 時參數有所變化,例如低版本配置數據庫 url時使用 url 屬性,高版本使用 jdbc-url 屬性,請注意區分

1.2.3 連接數據源配置文件

1.2.3.1 連接源配置一

@Configuration
@MapperScan(basePackages = "com.example.multipledatasource.mapper.db1", sqlSessionFactoryRef = "db1SqlSessionFactory")
public class DataSourceConfig1 {

    @Primary // 表示這個數據源是默認數據源, 這個注解必須要加,因為不加的話spring將分不清楚那個為主數據源(默認數據源)
    @Bean("db1DataSource")
    @ConfigurationProperties(prefix = "spring.datasource.db1") //讀取application.yml中的配置參數映射成為一個對象
    public DataSource getDb1DataSource(){
        return DataSourceBuilder.create().build();
    }

    @Primary
    @Bean("db1SqlSessionFactory")
    public SqlSessionFactory db1SqlSessionFactory(@Qualifier("db1DataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        // mapper的xml形式文件位置必須要配置,不然將報錯:no statement (這種錯誤也可能是mapper的xml中,namespace與項目的路徑不一致導致)
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapping/db1/*.xml"));
        return bean.getObject();
    }

    @Primary
    @Bean("db1SqlSessionTemplate")
    public SqlSessionTemplate db1SqlSessionTemplate(@Qualifier("db1SqlSessionFactory") SqlSessionFactory sqlSessionFactory){
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

1.2.3.2 連接源配置二

@Configuration
@MapperScan(basePackages = "com.example.multipledatasource.mapper.db2", sqlSessionFactoryRef = "db2SqlSessionFactory")
public class DataSourceConfig2 {

    @Bean("db2DataSource")
    @ConfigurationProperties(prefix = "spring.datasource.db2")
    public DataSource getDb1DataSource(){
        return DataSourceBuilder.create().build();
    }

    @Bean("db2SqlSessionFactory")
    public SqlSessionFactory db1SqlSessionFactory(@Qualifier("db2DataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapping/db2/*.xml"));
        return bean.getObject();
    }

    @Bean("db2SqlSessionTemplate")
    public SqlSessionTemplate db1SqlSessionTemplate(@Qualifier("db2SqlSessionFactory") SqlSessionFactory sqlSessionFactory){
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

1.2.4 項目結構

在這里插入圖片描述
注意事項:
service 層中根據不同的業務注入不同的 dao
如果是主從復制- -讀寫分離:比如 db1 中負責增刪改,db2 中負責查詢。但是需要注意的是負責增刪改的數據庫必須是主庫(master)

1.3 springboot+druid+mybatisplus使用注解整合

1.3.1 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-parent</artifactId>
       <version>2.1.9.RELEASE</version>
       <relativePath/> <!-- lookup parent from repository -->
   </parent>
   <groupId>com.example</groupId>
   <artifactId>mutipledatasource2</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <name>mutipledatasource2</name>
   <description>Demo project for Spring Boot</description>

   <properties>
       <java.version>1.8</java.version>
   </properties>

   <dependencies>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>
       <dependency>
           <groupId>com.baomidou</groupId>
           <artifactId>mybatis-plus-boot-starter</artifactId>
           <version>3.2.0</version>
       </dependency>
       <dependency>
           <groupId>com.baomidou</groupId>
           <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
           <version>2.5.6</version>
       </dependency>
       <dependency>
           <groupId>mysql</groupId>
           <artifactId>mysql-connector-java</artifactId>
           <scope>runtime</scope>
       </dependency>
       <dependency>
           <groupId>com.alibaba</groupId>
           <artifactId>druid-spring-boot-starter</artifactId>
           <version>1.1.20</version>
       </dependency>
       <dependency>
           <groupId>org.projectlombok</groupId>
           <artifactId>lombok</artifactId>
           <optional>true</optional>
       </dependency>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-test</artifactId>
           <scope>test</scope>
       </dependency>
   </dependencies>

   <build>
       <plugins>
           <plugin>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-maven-plugin</artifactId>
           </plugin>
       </plugins>
   </build>

   <profiles>
       <profile>
           <id>local1</id>
           <properties>
               <profileActive>local1</profileActive>
           </properties>
           <activation>
               <activeByDefault>true</activeByDefault>
           </activation>
       </profile>
       <profile>
           <id>local2</id>
           <properties>
               <profileActive>local2</profileActive>
           </properties>
       </profile>
   </profiles>
</project>

1.3.2 application.yml 配置文件

server:
  port: 8080
spring:
  datasource:
    dynamic:
      primary: db1 # 配置默認數據庫
      datasource:
        db1: # 數據源1配置
          url: jdbc:mysql://localhost:3306/db1?characterEncoding=utf8&useUnicode=true&useSSL=false&serverTimezone=GMT%2B8
          username: root
          password: root
          driver-class-name: com.mysql.cj.jdbc.Driver
        db2: # 數據源2配置
          url: jdbc:mysql://localhost:3306/db2?characterEncoding=utf8&useUnicode=true&useSSL=false&serverTimezone=GMT%2B8
          username: root
          password: root
          driver-class-name: com.mysql.cj.jdbc.Driver
      druid:
        initial-size: 1
        max-active: 20
        min-idle: 1
        max-wait: 60000
  autoconfigure:
    exclude:  com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 去除druid配置

DruidDataSourceAutoConfigure會注入一個DataSourceWrapper,其會在原生的spring.datasource下找 url, username, password 等。動態數據源 URL 等配置是在 dynamic 下,因此需要排除,否則會報錯。排除方式有兩種,一種是上述配置文件排除,還有一種可以在項目啟動類排除

@SpringBootApplication(exclude = DruidDataSourceAutoConfigure.class)
public class Application {
  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}

1.3.3 使用@DS區分數據源

給使用非默認數據源添加注解@DS
@DS可以注解在 方法 上和 上,同時存在方法注解優先於類上注解。
注解在 service 實現或 mapper 接口方法上,不要同時在 servicemapper 注解

mapper上使用

@DS("db2") 
public interface UserMapper extends BaseMapper<User> {
}

service上使用

@Service
@DS("db2")
public class ModelServiceImpl extends ServiceImpl<ModelMapper, Model> implements IModelService {}

方法上使用

@Select("SELECT * FROM user")
@DS("db2")
List<User> selectAll();

轉載於:https://www.cnblogs.com/aizen-sousuke/p/11756279.html

1.3.4 @Transaction和@DS問題

點擊了解當一起使用@Transaction和@DS時@DS失效問題

1.4 讀寫分離庫

讀寫分離庫使用AbstractRoutingDataSource
AbstractRoutingDataSource類和aop結合,還可以用來作為讀寫分離庫

1.4.1 AbstractRoutingDataSource原理

AbstractRoutingDataSource原理:

  1. Map<Object, Object> targetDataSources 保存了所有可能的數據源,key為數據庫的keyvalueDataSource對象或字符串形式的連接信息
  2. Object defaultTargetDataSource 保存了默認的數據源,用於找不到具體的數據源時使用
  3. afterPropertiesSet() 方法
    解析targetDataSources數據源信息成<key,DataSource>的形式,保存在Map<Object, DataSource> resolvedDataSources
    defaultTargetDataSource中的默認數據源信息解析成 DataSource對象保存在 DataSource resolvedDefaultDataSource
  4. determineCurrentLookupKey() 提供給子類重寫,指定當前線程使用的具體的數據源的key
  5. determineTargetDataSource() 根據 determineCurrentLookupKey()方法返回的key 返回數據源DataSouce對象,若沒有,則使用默認數據源對象
  6. getConnection() 根據determineTargetDataSource()返回的數據源,與其建立連接

1.4.2 ThreadLocal工具類

創建一個類用於操作 ThreadLocal,主要是通過get,set,remove方法來獲取、設置、刪除當前線程對應的數據源。

public class DataSourceContextHolder {
    //此類提供線程局部變量。這些變量不同於它們的正常對應關系是每個線程訪問一個線程(通過get、set方法),有自己的獨立初始化變量的副本。
    private static final ThreadLocal<String> DATASOURCE_HOLDER = new ThreadLocal<>();
    /**
     * 設置數據源
     */
    public static void setDataSource(String dataSourceName){
        DATASOURCE_HOLDER.set(dataSourceName);
    }
    /**
     * 獲取當前線程的數據源
     */
    public static String getDataSource(){
        return DATASOURCE_HOLDER.get();
    }
    /**
     * 刪除當前數據源
     */
    public static void removeDataSource(){
        DATASOURCE_HOLDER.remove();
    }
}

1.4.3 繼承AbstractRoutingDataSource

定義一個動態數據源繼承 AbstractRoutingDataSource,通過determineCurrentLookupKey方法與上述實現的ThreadLocal類中的get方法進行關聯,實現動態切換數據源。

/**
 * @description: 實現動態數據源,根據AbstractRoutingDataSource路由到不同數據源中
 */
public class DynamicDataSource extends AbstractRoutingDataSource {

    public DynamicDataSource(DataSource defaultDataSource,Map<Object, Object> targetDataSources){
        super.setDefaultTargetDataSource(defaultDataSource);
        super.setTargetDataSources(targetDataSources);
    }

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

上述代碼中,還實現了一個動態數據源類的構造方法,主要是為了設置默認數據源,以及以Map保存的各種目標數據源。其中Mapkey是設置的數據源名稱,value則是對應的數據源(DataSource)

1.4.4 配置數據源

配置文件

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      master:
        url: jdbc:mysql://xxxxxx:3306/test1?characterEncoding=utf-8&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull&useSSL=false
        username: xxxx
        password: xxxx
        driver-class-name: com.mysql.cj.jdbc.Driver
      slave:
        url: jdbc:mysql://xxxxx:3306/test2?characterEncoding=utf-8&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull&useSSL=false
        username: xxxx
        password: xxxx
        driver-class-name: com.mysql.cj.jdbc.Driver

配置類

/**
 * @description: 設置數據源
 **/
@Configuration
public class DateSourceConfig {

    @Bean
    @ConfigurationProperties("spring.datasource.druid.master")
    public DataSource masterDataSource(){
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties("spring.datasource.druid.slave")
    public DataSource slaveDataSource(){
        return DruidDataSourceBuilder.create().build();
    }

    @Bean(name = "dynamicDataSource")
    @Primary
    public DynamicDataSource createDynamicDataSource(){
        Map<Object,Object> dataSourceMap = new HashMap<>();
        DataSource defaultDataSource = masterDataSource();
        dataSourceMap.put("master",defaultDataSource);
        dataSourceMap.put("slave",slaveDataSource());
        return new DynamicDataSource(defaultDataSource,dataSourceMap);
    }
}

通過配置類,將配置文件中的配置的數據庫信息轉換成datasource,並添加到DynamicDataSource中,同時通過@BeanDynamicDataSource注入Spring中進行管理,后期在進行動態數據源添加時,會用到。

1.4.5 測試

我們創建一個getData的方法,參數就是需要查詢數據的數據源名稱。

@GetMapping("/getData.do/{datasourceName}")
public String getMasterData(@PathVariable("datasourceName") String datasourceName){
    DataSourceContextHolder.setDataSource(datasourceName);
    TestUser testUser = testUserMapper.selectOne(null);
    DataSourceContextHolder.removeDataSource();
    return testUser.getUserName();
}

在上述代碼中,我們看到DataSourceContextHolder.setDataSource(datasourceName); 來設置了當前線程需要查詢的數據庫,通過DataSourceContextHolder.removeDataSource(); 來移除當前線程已設置的數據源。
使用過Mybatis-plus動態數據源的小伙伴,應該還記得我們在使用切換數據源時會使用到DynamicDataSourceContextHolder.push(String ds);DynamicDataSourceContextHolder.poll(); 這兩個方法,翻看源碼我們會發現其實就是在使用ThreadLocal時使用了棧,這樣的好處就是能使用多數據源嵌套

注:啟動程序時,小伙伴不要忘記將SpringBoot自動添加數據源進行排除哦,否則會報循環依賴問題。

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)

1.4.6 使用自定義注解

在上述中,雖然已經實現了動態切換數據源,但是我們會發現如果涉及到多個業務進行切換數據源的話,我們就需要在每一個實現類中添加這一段代碼。假如使用注解來進行優化呢,如下

1.4.6.1 定義注解

我們就用mybatis動態數據源切換的注解:DS,代碼如下:

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface DS {
    String value() default "master";
}

1.4.6.2 實現aop

@Aspect
@Component
@Slf4j
public class DSAspect {

    @Pointcut("@annotation(com.test.dynamic_datasource.dynamic.aop.DS)")
    public void dynamicDataSource(){}

    @Around("dynamicDataSource()")
    public Object datasourceAround(ProceedingJoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature)point.getSignature();
        Method method = signature.getMethod();
        DS ds = method.getAnnotation(DS.class);
        if (Objects.nonNull(ds)){
            DataSourceContextHolder.setDataSource(ds.value());
        }
        try {
            return point.proceed();
        } finally {
            DataSourceContextHolder.removeDataSource();
        }
    }
}

代碼使用了@Around,通過ProceedingJoinPoint獲取注解信息,拿到注解傳遞值,然后設置當前線程的數據源。

1.4.7 動態添加數據源

業務場景 :有時候我們的業務會要求我們從保存有其他數據源的數據庫表中添加這些數據源,然后再根據不同的情況切換這些數據源。因此我們需要改造下 DynamicDataSource 來實現動態加載數據源。

1.4.7.1 數據源實體

@Data
@Accessors(chain = true)
public class DataSourceEntity {
    /**
     * 數據庫地址
     */
    private String url;
    /**
     * 數據庫用戶名
     */
    private String userName;
    /**
     * 密碼
     */
    private String passWord;
    /**
     * 數據庫驅動
     */
    private String driverClassName;
    /**
     * 數據庫key,即保存Map中的key
     */
    private String key;
}

實體中定義數據源的一般信息,同時定義一個key用於作為DynamicDataSourceMap中的key

1.4.7.2 修改DynamicDataSource

/**
 * @description: 實現動態數據源,根據AbstractRoutingDataSource路由到不同數據源中
 */
@Slf4j
public class DynamicDataSource extends AbstractRoutingDataSource {

    private final Map<Object,Object> targetDataSourceMap;

    public DynamicDataSource(DataSource defaultDataSource,Map<Object, Object> targetDataSources){
        super.setDefaultTargetDataSource(defaultDataSource);
        super.setTargetDataSources(targetDataSources);
        this.targetDataSourceMap = targetDataSources;
    }

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

    /**
     * 添加數據源信息
     * @param dataSources 數據源實體集合
     * @return 返回添加結果
     */
    public Boolean createDataSource(List<DataSourceEntity> dataSources){
        try {
            if (CollectionUtils.isNotEmpty(dataSources)){
                for (DataSourceEntity ds : dataSources) {
                    //校驗數據庫是否可以連接
                    Class.forName(ds.getDriverClassName());
                    DriverManager.getConnection(ds.getUrl(),ds.getUserName(),ds.getPassWord());
                    //定義數據源
                    DruidDataSource dataSource = new DruidDataSource();
                    BeanUtils.copyProperties(ds,dataSource);
                    //申請連接時執行validationQuery檢測連接是否有效,這里建議配置為TRUE,防止取到的連接不可用
                    dataSource.setTestOnBorrow(true);
                    //建議配置為true,不影響性能,並且保證安全性。
                    //申請連接的時候檢測,如果空閑時間大於timeBetweenEvictionRunsMillis,執行validationQuery檢測連接是否有效。
                    dataSource.setTestWhileIdle(true);
                    //用來檢測連接是否有效的sql,要求是一個查詢語句。
                    dataSource.setValidationQuery("select 1 ");
                    dataSource.init();
                    this.targetDataSourceMap.put(ds.getKey(),dataSource);
                }
                super.setTargetDataSources(this.targetDataSourceMap);
                // 將TargetDataSources中的連接信息放入resolvedDataSources管理
                super.afterPropertiesSet();
                return Boolean.TRUE;
            }
        }catch (ClassNotFoundException | SQLException e) {
            log.error("---程序報錯---:{}", e.getMessage());
        }
        return Boolean.FALSE;
    }

    /**
     * 校驗數據源是否存在
     * @param key 數據源保存的key
     * @return 返回結果,true:存在,false:不存在
     */
    public boolean existsDataSource(String key){
        return Objects.nonNull(this.targetDataSourceMap.get(key));
    }
}

在改造后的DynamicDataSource中,我們添加可以一個 private final Map<Object,Object> targetDataSourceMap,這個map會在添加數據源的配置文件時將創建的Map數據源信息通過DynamicDataSource構造方法進行初始賦值,即:DateSourceConfig類中的createDynamicDataSource()方法中。

同時我們在該類中添加了一個createDataSource方法,進行數據源的創建,並添加到map中,再通過super.setTargetDataSources(this.targetDataSourceMap);進行目標數據源的重新賦值

1.4.7.3 動態添加數據源

上述代碼已經實現了添加數據源的方法,那么我們來模擬通過從數據庫表中添加數據源,然后我們通過調用加載數據源的方法將數據源添加進數據源Map中。

在主數據庫中定義一個數據庫表,用於保存數據庫信息。

create table test_db_info(
    id int auto_increment primary key not null comment '主鍵Id',
    url varchar(255) not null comment '數據庫URL',
    username varchar(255) not null comment '用戶名',
    password varchar(255) not null comment '密碼',
    driver_class_name varchar(255) not null comment '數據庫驅動'
    name varchar(255) not null comment '數據庫名稱'
)

為了方便,我們將之前的從庫錄入到數據庫中,修改數據庫名稱。

insert into test_db_info(url, username, password,driver_class_name, name)
value ('jdbc:mysql://xxxxx:3306/test2?characterEncoding=utf-8&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull&useSSL=false',
       'root','123456','com.mysql.cj.jdbc.Driver','add_slave')

1.4.7.4 啟動添加配置

啟動SpringBoot時添加數據源:

@Component
public class LoadDataSourceRunner implements CommandLineRunner {
    @Resource
    private DynamicDataSource dynamicDataSource;
    @Resource
    private TestDbInfoMapper testDbInfoMapper;
    @Override
    public void run(String... args) throws Exception {
        List<TestDbInfo> testDbInfos = testDbInfoMapper.selectList(null);
        if (CollectionUtils.isNotEmpty(testDbInfos)) {
            List<DataSourceEntity> ds = new ArrayList<>();
            for (TestDbInfo testDbInfo : testDbInfos) {
                DataSourceEntity sourceEntity = new DataSourceEntity();
                BeanUtils.copyProperties(testDbInfo,sourceEntity);
                sourceEntity.setKey(testDbInfo.getName());
                ds.add(sourceEntity);
            }
            dynamicDataSource.createDataSource(ds);
        }
    }
}


免責聲明!

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



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