多数据源的springboot进行动态连接方案

多数据源的springboot进行动态连接方案

多数据源是实际开发中很常见的需求,比如同时操作主数据库和从数据库、或者不同业务的数据库,Spring Boot 提供了灵活的配置方式,我会用通俗易懂的方式带你实现。

核心实现思路

实现多数据源的核心是:

配置多个数据源的连接信息(URL、用户名、密码等);

为每个数据源创建独立的 DataSource 实例;

为每个数据源配置对应的 SqlSessionFactory(MyBatis 场景)或 EntityManagerFactory(JPA 场景);

指定不同包 / 类使用对应的数据源(通过注解或配置区分)。

Springboot的基础配置yml设置连接

java 复制代码
jdbc:
  dbType: mysql
  url:
    ecg: jdbc:mysql://localhost:3306/ecg?serverFTimezone=CTT&useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
    username:
    ecg: root
  password:
    ecg: root

在config获取配置yml内容

java 复制代码
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Data
@Component
@ConfigurationProperties(prefix = "jdbc")
public class JdbcConfig {

    @Value("${jdbc.dbType}")
    private String dbType;

    @Value("${jdbc.url.ecg}")
    private String urlEcg;

    @Value("${jdbc.username.ecg}")
    private String usernameEcg;


    @Value("${jdbc.password.ecg}")
    private String passwordEcg;

}

Config目录下面的子文件夹properties下的dataconfig.java进行配置

java 复制代码
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.sql.SQLException;
import java.util.Properties;

@Configuration
public class DataSourceConfig {

    @Autowired
    private JdbcConfig jdbcConfig;

    @Bean(name = "ecg", initMethod = "init", destroyMethod = "close")
    public DruidDataSource dataSource_ecg() throws SQLException {
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setUrl(jdbcConfig.getUrlEcg());
        druidDataSource.setUsername(jdbcConfig.getUsernameEcg());
        druidDataSource.setPassword(jdbcConfig.getPasswordEcg());
        druidDataSource.setInitialSize(1);
        druidDataSource.setMaxActive(20);
        druidDataSource.setMinIdle(3);
        druidDataSource.setMaxWait(60000);
        druidDataSource.setTimeBetweenEvictionRunsMillis(60000);
        druidDataSource.setMinEvictableIdleTimeMillis(300000);
        druidDataSource.setValidationQuery("SELECT 1");
        druidDataSource.setTestOnBorrow(true);
        druidDataSource.setTestOnReturn(false);
        druidDataSource.setTestWhileIdle(true);
        druidDataSource.setFilters("stat");
        druidDataSource.setRemoveAbandoned(true);
        druidDataSource.setRemoveAbandonedTimeout(3600);
        druidDataSource.setLogAbandoned(true);
        Properties properties = new Properties();
        properties.put("remarksReporting", "true");
        druidDataSource.setConnectProperties(properties);
        return druidDataSource;
    }

连接数据库表中的动态数据源

java 复制代码
import java.util.HashMap;
import java.util.Map;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.GenericGenerator;

@Entity
@Table(name = "data_source", schema = "")
@DynamicUpdate(true)
@DynamicInsert(true)
@SuppressWarnings("serial")
public class DynamicDataSourceEntity implements java.io.Serializable {
      
   /**id*/
   private java.lang.String id;
   /**dbKey*/
   private java.lang.String dbKey;
   /**description*/
   private java.lang.String description;
   /**driverClass*/
   private java.lang.String driverClass;
   /**url*/
   private java.lang.String url;
   /**dbUser*/
   private java.lang.String dbUser;
   /**dbPassword*/
   private java.lang.String dbPassword;
   /**dbType*/
   private java.lang.String dbType;
   /**dbName*/
   private java.lang.String dbName;
   
   /**
    *方法: 取得java.lang.String
    *@return: java.lang.String  id
    */
   
   @Id
   @GeneratedValue(generator = "paymentableGenerator")
   @GenericGenerator(name = "paymentableGenerator", strategy = "uuid")
   @Column(name ="ID",nullable=false,precision=36,length=36)
   public java.lang.String getId(){
      return this.id;
   }

   /**
    *方法: 设置java.lang.String
    *@param: java.lang.String  id
    */
   public void setId(java.lang.String id){
      this.id = id;
   }
   /**
    *方法: 取得java.lang.String
    *@return: java.lang.String  dbKey
    */
   @Column(name ="DB_KEY",nullable=false,precision=50,length=50)
   public java.lang.String getDbKey(){
      return this.dbKey;
   }

   /**
    *方法: 设置java.lang.String
    *@param: java.lang.String  dbKey
    */
   public void setDbKey(java.lang.String dbKey){
      this.dbKey = dbKey;
   }
   /**
    *方法: 取得java.lang.String
    *@return: java.lang.String  description
    */
   @Column(name ="DESCRIPTION",nullable=false,precision=50,length=50)
   public java.lang.String getDescription(){
      return this.description;
   }

   /**
    *方法: 设置java.lang.String
    *@param: java.lang.String  description
    */
   public void setDescription(java.lang.String description){
      this.description = description;
   }
   /**
    *方法: 取得java.lang.String
    *@return: java.lang.String  driverClass
    */
   @Column(name ="DRIVER_CLASS",nullable=false,precision=50,length=50)
   public java.lang.String getDriverClass(){
      return this.driverClass;
   }

   /**
    *方法: 设置java.lang.String
    *@param: java.lang.String  driverClass
    */
   public void setDriverClass(java.lang.String driverClass){
      this.driverClass = driverClass;
   }
   /**
    *方法: 取得java.lang.String
    *@return: java.lang.String  url
    */
   @Column(name ="URL",nullable=false,precision=100,length=100)
   public java.lang.String getUrl(){
      return this.url;
   }

   /**
    *方法: 设置java.lang.String
    *@param: java.lang.String  url
    */
   public void setUrl(java.lang.String url){
      this.url = url;
   }
   /**
    *方法: 取得java.lang.String
    *@return: java.lang.String  dbUser
    */
   @Column(name ="DB_USER",nullable=false,precision=50,length=50)
   public java.lang.String getDbUser(){
      return this.dbUser;
   }

   /**
    *方法: 设置java.lang.String
    *@param: java.lang.String  dbUser
    */
   public void setDbUser(java.lang.String dbUser){
      this.dbUser = dbUser;
   }
   /**
    *方法: 取得java.lang.String
    *@return: java.lang.String  dbPassword
    */
   @Column(name ="DB_PASSWORD",nullable=true,precision=50,length=50)
   public java.lang.String getDbPassword(){
      return this.dbPassword;
   }

   /**
    *方法: 设置java.lang.String
    *@param: java.lang.String  dbPassword
    */
   public void setDbPassword(java.lang.String dbPassword){
      this.dbPassword = dbPassword;
   }
   /**
    *方法: 取得java.lang.String
    *@return: java.lang.String  dbType
    */
   @Column(name ="DB_TYPE",nullable=true,precision=50,length=50)
   public java.lang.String getDbType(){
      return this.dbType;
   }

   /**
    *方法: 设置java.lang.String
    *@param: java.lang.String  dbType
    */
   public void setDbType(java.lang.String dbType){
      this.dbType = dbType;
   }

   /**
    *方法: 取得java.lang.String
    *@return: java.lang.String  dbName
    */
   @Column(name ="DB_NAME",nullable=true,precision=50,length=50)
   public java.lang.String getDbName() {
      return dbName;
   }

   /**
    *方法: 设置java.lang.String
    *@param: java.lang.String  dbName
    */
   public void setDbName(java.lang.String dbName) {
      this.dbName = dbName;
   }

}

测试连接情况

java 复制代码
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;


import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
public class DynamicDBTest extends AbstractUnitTest {
   static String dbKey = "ECG_LOCAL";
   @Autowired
   private CacheServiceI cacheService;

   /**
    * 定义多数据源配置
    */
   @Before
   public void initDB(){
      DynamicDataSourceEntity dynamicSourceEntity = new DynamicDataSourceEntity();
      String driverClassName = "com.mysql.cj.jdbc.Driver";
      String url = "jdbc:mysql://localhost:3306/ecg";
      String dbUser = "root";
      String dbPassword = "root";

      dynamicSourceEntity.setDbKey(dbKey);
      dynamicSourceEntity.setDriverClass(driverClassName);
      dynamicSourceEntity.setUrl(url);
      dynamicSourceEntity.setDbUser(dbUser);
      dynamicSourceEntity.setDbPassword(dbPassword);

      Map<String, DynamicDataSourceEntity> dynamicDataSourceMap = new HashMap<String, DynamicDataSourceEntity>();
      dynamicDataSourceMap.put(dbKey, dynamicSourceEntity);
      //缓存数据
      cacheService.put(CacheServiceI.FO_CACHE,ResourceUtil.DY_DB_CONFIGS_FOREVER_CACHE_KEY,dynamicDataSourceMap);
   }
@Test
   public void testInsert() throws Exception {
      String id = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
      // 测试查询列表
      String sql = "insert ecg (id,name)values(?,'DynamicDBTest-insert') ";
      DynamicDBUtil.update(dbKey,sql,id);
      System.out.println("-----------testInsert---------");
   }

   @Test
   public void testUpdate() throws Exception {
      // 测试查询列表
      String sql = "update ecg set name='动态数据库源测试' where id = '4'";
      DynamicDBUtil.update(dbKey,sql);
      System.out.println("-----------testUpdate---------");
   }


   @Test
   public void testSelectList() throws Exception {
      // 测试查询列表
      String sql = "select * from ecg";
      List<Map<String, Object>> list = DynamicDBUtil.findList(dbKey, sql);
      System.out.println("---------------testSelectList------listSize--------"+ list.size());
      for (Map<String, Object> mp : list) {
         System.out.println(mp.toString());
      }
   }

   @Test
   public void testActionEntity(){
      String sql = "<#if nlevel gt 2> insert into TEST003(id, sname, nlevel) values ((select maxid from (select ifnull(max(id)+1,1) maxid from TEST003) a),"
            + " :sname, :nlevel)</#if>";
      HashMap<String, Object> data = new HashMap<String, Object>();
      data.put("sname", "aaa");
      data.put("nlevel", 3);
      DynamicDBUtil.updateByHash(dbKey, sql, data);

      sql = "SELECT * FROM TEST003 WHERE id = :id";data = new HashMap<String, Object>();
      data.put("id", 1);
      Map<String, Object> aaa = (Map<String, Object>) DynamicDBUtil.findOneByHash(dbKey, sql, data);
      System.out.println(aaa.get("sname"));

      sql = "SELECT * FROM TEST003 WHERE id >= '${id}'";data = new HashMap<String, Object>();
      data.put("id", 2);
      List<Test> bbb = DynamicDBUtil.findListEntrysByHash(dbKey, sql, Test.class, data);
      System.out.println(bbb);
   }

}
相关推荐
w***76552 小时前
SpringBoot集成MQTT客户端
java·spring boot·后端
HABuo2 小时前
【Linux进程(五)】进程地址空间深入剖析-->虚拟地址、物理地址、逻辑地址的区分
linux·运维·服务器·c语言·c++·后端·centos
编程饭碗2 小时前
【多线程编程】
java·开发语言
北鹿不麋鹿2 小时前
自学Java手记:Map集合,Arrays工具类和Lambda表达式
java
码头整点薯条2 小时前
对接第三方服务踩坑:属性大小写不匹配导致数据解析失败,一个注解搞定!
java
Wpa.wk2 小时前
性能测试工具 - JMeter工具组件介绍一
java·经验分享·测试工具·jmeter·性能测试
虫小宝2 小时前
个微iPad协议场景下Java后端的协议解析异常排查与问题定位技巧
java·svn·ipad
程序媛徐师姐2 小时前
Java基于微信小程序的鲜花销售系统,附源码+文档说明
java·微信小程序·鲜花销售小程序·java鲜花销售小程序·鲜花销售微信小程序·java鲜花销售系统小程序·java鲜花销售微信小程序
IT_陈寒2 小时前
SpringBoot 3.x实战:5个高效开发技巧让我减少了40%重复代码
前端·人工智能·后端