SpringBoot多数据源(一)

8 篇文章 0 订阅
5 篇文章 0 订阅

1.多数据源使用场景

1.1 业务复杂(数据量大)

简单理解就是业务量复杂,将庞大的数据拆到多个数据库中。或者由于公司有多个子项目,各用各的数据库,涉及数据共享

1.2 读写分离

为了解决数据库的读性能瓶颈(读比写性能更高,写锁会影响读阻塞,从而影响读的性能)

与上述1.1不同的是,在读写分离中,主库和从库的数据库是一致的(不考虑主从延迟)。数据更新操作(insertupdatedelete)都是在主库上进行的,主库将数据更新信息同步给
从库。在查询时,可以在从库上进行。从而分担主库的压力。

2.多数据源配置

spring:
  datasource:
    #数据源1
    datasource1:
      driver-class-name: com.mysql.cj.jdbc.Driver
      jdbc-url: jdbc:mysql://localhost:3306/test_master
      username: root
      password: root
      druid:
         initial-size: 1
         min-idle: 1
         max-active: 20
         test-on-borrow: true

    #数据源2
    datasource2:
      driver-class-name: com.mysql.cj.jdbc.Driver
      jdbc-url: jdbc:mysql://localhost:3306/test_slave
      username: root
      password: root
      druid:
        initial-size: 1
        min-idle: 1
        max-active: 20
        test-on-borrow: true

# mybatis的配置
mybatis:
  type-aliases-package: com.rql.entity
  mapper-locations: classpath:mybatis/*.xml

这里在配置时,特别注意在使用多配置源时,要将url改为jdbc-url

对应两个数据库:

在这里插入图片描述

3.应用

下面是一个简单的SpringBoot整合mybatis的项目目录层级:

在这里插入图片描述

其中DataSourceConfig用于定义DataSource Bean,并通过@ConfigurationProperties注解将配置文件中的属性映射到该Bean的属性上
DataSourceConfig.java

@Configuration
public class DataSourceConfig {

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

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

上面只是创建了两个DataSourceBean,分别为dataSource1dataSource2,如果想要动态地根据操作去调用不同的数据源,那么就需要再创建一个Bean,类似于代理的角色,根据条件来选择不同的数据源。

因此,创建DynamicDataSource.java,并实现了DataSource接口。



@Component
@Primary
public class DynamicDataSource implements DataSource, InitializingBean {

    public static ThreadLocal<String> name=new ThreadLocal<>();

    @Autowired
    DataSource dataSource1;

    @Autowired
    DataSource dataSource2;

    @Override
    public Connection getConnection() throws SQLException {
        if (name.get().equals("w")) {
            return dataSource1.getConnection();
        }
        else {
            return dataSource2.getConnection();
        }
    }

    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        return null;
    }

    @Override
    public PrintWriter getLogWriter() throws SQLException {
        return null;
    }

    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {

    }

    @Override
    public void setLoginTimeout(int seconds) throws SQLException {

    }

    @Override
    public int getLoginTimeout() throws SQLException {
        return 0;
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return null;
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }

    @Override
    public void afterPropertiesSet() throws Exception {

        name.set("w");
    }
}

这里主要通过getConnection()方法来选择需要连接的数据源,因此根据读写操作的不同,设置一个值来区别(一般是使用枚举值,这样后面修改时不至于到代码中挨个去找),文中主要设置了一个参数,为了讲述方面。

public static ThreadLocal<String> name=new ThreadLocal<>();

注意到DynamicDataSource.java也实现了InitializingBean 接口。

InitializingBean接口是Spring Framework中的一个重要接口,其主要目的是在Bean实例化后进行初始化操作。具体来说,当一个Bean实现了InitializingBean接口并被Spring容器创建后,Spring会在该Bean的属性设置完成后自动调用afterPropertiesSet()方法来执行一些额外的初始化逻辑。

因此,这里在Bean实例化后,设置了name的初始值。

4.测试

@RestController
@RequestMapping("user")
public class UserController {

    @Autowired
    private UserDao userDao;

    @GetMapping("/a")
    public List<User> selectUsers(){
        DynamicDataSource.name.set("r");
        return userDao.findAll();
    }

    @PostMapping("/b")
    public void insertUser(@RequestBody User user){
        DynamicDataSource.name.set("w");
        userDao.inserUser(user);
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值