springboot集成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>

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

其中,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();
    }
}

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

4. 手动切换数据源

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

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

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

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

    }

上述代码中,执行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);
        
    }
	

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);
    }


}

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

	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;
    }

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

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot集成dynamic-datasource可以帮助我们实现动态数据源切换的功能。面是一些基本步骤: 1. 添加依赖:在pom.xml文件中添加dynamic-datasource的依赖。 ```xml <dependency> <groupId>com.baomidou</groupId> <artifactId>dynamic-datasource-spring-boot-starter</artifactId> <version>latest-version</version> </dependency> ``` 2. 配置数据源:在application.properties或application.yml文件中配置数据源信息。 ```properties # 数据源1 spring.datasource.dynamic.datasource.master.url=jdbc:mysql://localhost:3306/db1 spring.datasource.dynamic.datasource.master.username=root spring.datasource.dynamic.datasource.master.password=123456 spring.datasource.dynamic.datasource.master.driver-class-name=com.mysql.jdbc.Driver # 数据源2 spring.datasource.dynamic.datasource.slave.url=jdbc:mysql://localhost:3306/db2 spring.datasource.dynamic.datasource.slave.username=root spring.datasource.dynamic.datasource.slave.password=123456 spring.datasource.dynamic.datasource.slave.driver-class-name=com.mysql.jdbc.Driver ``` 3. 配置动态数据源:创建一个配置类,用于配置动态数据源。 ```java @Configuration public class DynamicDataSourceConfig { @Primary @Bean("dynamicDataSource") @ConfigurationProperties(prefix = "spring.datasource.dynamic") public DataSource dynamicDataSource() { return new DruidDataSource(); } @Bean public DataSourceTransactionManager transactionManager(@Qualifier("dynamicDataSource") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } @Bean public SqlSessionFactory sqlSessionFactory(@Qualifier("dynamicDataSource") DataSource dataSource) throws Exception { MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource); return sessionFactory.getObject(); } } ``` 4. 使用动态数据源:在需要使用数据源的地方,通过注解`@DS`指定数据源。 ```java @Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override @DS("master") // 使用master数据源 public List<User> getMasterUsers() { return userMapper.getUsers();

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值