SpringBoot多数据源(一)
- 1.多数据源使用场景
 - 1.1 业务复杂(数据量大)
 - 1.2 读写分离
 
- 2.多数据源配置
 - 3.应用
 - 4.测试
 
1.多数据源使用场景
1.1 业务复杂(数据量大)
简单理解就是业务量复杂,将庞大的数据拆到多个数据库中。或者由于公司有多个子项目,各用各的数据库,涉及数据共享
1.2 读写分离
为了解决数据库的读性能瓶颈(读比写性能更高,写锁会影响读阻塞,从而影响读的性能)。
与上述1.1不同的是,在读写分离中,主库和从库的数据库是一致的(不考虑主从延迟)。数据更新操作(insert 、update、delete)都是在主库上进行的,主库将数据更新信息同步给
 从库。在查询时,可以在从库上进行。从而分担主库的压力。
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();
    }
}
 
上面只是创建了两个DataSource的Bean,分别为dataSource1和dataSource2,如果想要动态地根据操作去调用不同的数据源,那么就需要再创建一个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);
    }
}
                


















