当前位置:   article > 正文

springboot集成dynamic-datasource 多数据源手动切换 动态添加删除_dynamic-datasource 多数据源 动态添加删除

dynamic-datasource 多数据源 动态添加删除


Spring Boot集成Dynamic-datasource实现多数据源切换与动态管理,动态数据源可以与配置文件的数据源合并管理,的步骤如下:

1. 引入依赖

在pom.xml文件中加入以下依赖:

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>3.2.0</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5

2. 配置数据源

在application.yml或application.properties中配置数据源,如:

spring:
  datasource:
    dynamic:
      primary: master #设置默认的数据源或者数据源组,默认值即为master
      strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
      datasource:
        master:
          url: jdbc:mysql://xx.xx.xx.xx:3306/dynamic
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver # 3.2.0开始支持SPI可省略此配置
        slave_1:
          url: jdbc:mysql://xx.xx.xx.xx:3307/dynamic
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver
        slave_2:
          url: jdbc:mysql://xx.xx.xx.xx:3308/dynamic
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver
       #......省略
       #以上会配置一个默认库master,一个组slave下有两个子库slave_1,slave_2

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

其中,spring.datasource.dynamic.primary为默认数据源,后面的配置为各个数据源的配置。

3. 注解切换数据源

在需要使用的地方使用@DS注解,指定使用的数据源,如:

//@DS("slave_1")
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @DS("slave_1")
    @Override
    public List<User> listUsersBySlave1() {
        return userMapper.listUsers();
    }
      
    @Override
    public List<User> listUsersByMaster() {
        return userMapper.listUsers();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

@DS 可以注解在方法上和类上,同时存在方法注解优先于类上注解,如果没有写@DS注解,则默认使用master数据源。

4. 手动切换数据源

有时候切换数据源需要根据业务动态切换,就不能使用注解,需要手动切换数据:

DynamicDataSourceContextHolder.push("slave_1");
//执行业务方法
DynamicDataSourceContextHolder.poll();
  • 1
  • 2
  • 3

手动切换数据源会与springboot事务冲突,例如

	@Transactional(rollbackFor = Exception.class)
    public void add(DataSourceAddVo vo) {
        DynamicDataSourceContextHolder.push("slave_1");
		//执行业务方法
		selectList();
		handleAdd();
		DynamicDataSourceContextHolder.poll();
       

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

上述代码中,执行handleAdd方法不能执行切换数据源,可以改造成:

	//@Transactional(rollbackFor = Exception.class)
    public void add(DataSourceAddVo vo) {
        DynamicDataSourceContextHolder.push("slave_1");
		//执行业务方法
		selectList();
		 
		DynamicDataSourceContextHolder.poll();
       
    }
 @Transactional(rollbackFor = Exception.class)
    public void handleAdd( ){
        this.save(bean);
        
    }
	
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

5. 动态管理数据源

以上切换的数据源都是在配置文件上定义好了,如果需要由用户从界面添加数据源则需要动态维护数据源。

数据源由:数据源唯一编码、用户名、密码、url和驱动4个元素组成,见下图:
在这里插入图片描述

编写数据源管理的工具类:

package org.bitnei.modules.ds;

import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.creator.DataSourceCreator;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.util.Set;

/**
 * 功能描述:数据源管理工具类
 *
 * @author: zenghaiwen
 * @date: 2023年07月20日 10:05
 */
@Component
@Slf4j
public class DynamicDataSourcesUtil {

    @Autowired
    private DataSource dataSource;

    @Autowired
    private DataSourceCreator dataSourceCreator;

    /**
     * 添加数据源
     */
    public Set<String> addDataSource(DataSourceDTO dto) {
        DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
        if(!this.existsDataSource(dto.getPoolName())){
            new JdbcTemplate(dataSource);
            DataSourceProperty dataSourceProperty = new DataSourceProperty();
            BeanUtils.copyProperties(dto, dataSourceProperty);

            DataSource dataSource = dataSourceCreator.createDataSource(dataSourceProperty);
            ds.addDataSource(dto.getPoolName(), dataSource);
        }
        return ds.getCurrentDataSources().keySet();
    }

    public DataSource getDataSource(){
        DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
        return  ds.getDataSource("master");
    }

    /**
     * 删除数据源
     * @param name
     */
    public void removeDataSource(String name){
        DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
        ds.removeDataSource(name);
    }

    /**
     * 获取当前所有数据源
     * @return
     */
    public Set<String> allDataSource() {
        DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
        return ds.getCurrentDataSources().keySet();
    }

    /**
     * 是否存在数据源
     * @param name
     * @return
     */
    public boolean existsDataSource(String name){

        DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
        return ds.getCurrentDataSources().containsKey(name);
    }


}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83

以下是调用工具类实现动态管理数据源的代码:

	public void add(DataSourceAddVo vo) {
         
        DataSource bean = BeanUtil.copyProperties(vo,DataSource.class);         

        //测试链接是否成功
        boolean isConnect = checkDataSource(bean);
        AssertUtils.assertIsTrue(isConnect,"无法链接数据库");

        //添加数据源
        Set<String> dbSet =  this.addDataSource(bean);
        //切换刚刚添加的数据源
        DynamicDataSourceContextHolder.push(bean.getCode());
        //执行业务方法
 
        DynamicDataSourceContextHolder.poll();

        handleAdd(bean,tableList,allVehicleList);

    }
	
	private Set<String> addDataSource(DataSource ds){
        DataSourceDTO dto = buildDataSourceDTO(ds);

        return dynamicDataSourcesUtil.addDataSource(dto);

    }
	private DataSourceDTO buildDataSourceDTO(DataSource ds){
        DataSourceDTO dto = new DataSourceDTO()
                .setPoolName(ds.getCode())
                .setUsername(ds.getUsername())
                .setPassword(ds.getPassword())
                .setUrl(ds.getDbUrl())
                .setDriverClassName(Constants.MYSQL_DRIVER);

        return dto;
    }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

注:添加数据源必须检查数据源的连通性,否则会一直打印数据源错误。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/677971
推荐阅读
相关标签
  

闽ICP备14008679号