多数据源的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);
   }

}
相关推荐
Hx_Ma166 小时前
SpringMVC框架提供的转发和重定向
java·开发语言·servlet
期待のcode7 小时前
原子操作类LongAdder
java·开发语言
舟舟亢亢7 小时前
Java集合笔记总结
java·笔记
小酒窝.7 小时前
【多线程】多线程打印ABC
java
乡野码圣8 小时前
【RK3588 Android12】RCU机制
java·jvm·数据库
JAVA+C语言8 小时前
如何优化 Java 多主机通信的性能?
java·开发语言·php
编程彩机9 小时前
互联网大厂Java面试:从分布式架构到大数据场景解析
java·大数据·微服务·spark·kafka·分布式事务·分布式架构
小酒窝.9 小时前
【多线程】多线程打印1~100
java·多线程
君爱学习9 小时前
基于SpringBoot的选课调查系统
java
APIshop10 小时前
Java 实战:调用 item_search_tmall 按关键词搜索天猫商品
java·开发语言·数据库