ShardingSphere-JDBC兼容dynamicDataSource实现多数据源

  • Post author:
  • Post category:其他




1. 背景



ShardingSphere-JDBC(5.1.1版本)读写分离示例

一文中介绍了ShardingJdbc(5.1.1)的使用,但该文中方法没有使用DynamicDataSource,如果一起使用的话会出现异常(Caused by: java.lang.IllegalArgumentException: Property ‘sqlSessionFactory’ or ‘sqlSessionTemplate’ are required),如果想要一起使用或者将ShardingSphere-JDBC集成到原DynamicDataSource项目中则需要对数据源进行修改,本质上就是将shardingDataSource作为DynamicDataSource的一个数据源,将sharding的数据源交由原Dynamic管理。



2. 数据源配置

将sharding的数据源交由原Dynamic管理

@Configuration
@AutoConfigureBefore({DynamicDataSourceAutoConfiguration.class, ShardingSphereAutoConfiguration.class})
@Slf4j
public class MrsszDataSourceConfig {
    @Autowired
    AbstractApplicationContext context;
    @Autowired
    private DynamicDataSourceProperties properties;
​
    @Lazy
    @Resource
    private DataSource shardingDataSource;
​
    @Bean
    public DynamicDataSourceProvider dynamicDataSourceProvider() {
        Map<String, DataSourceProperty> datasourceMap = properties.getDatasource();
        return new AbstractDataSourceProvider() {
            @Override
            public Map<String, DataSource> loadDataSources() {
                Map<String, DataSource> dataSourceMap = createDataSourceMap(datasourceMap);
                dataSourceMap.put("sharding-data-source", shardingDataSource);
                return dataSourceMap;
            }
        };
    }
​
    @Primary
    @Bean
    public DataSource dataSource() {
        DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();
        dataSource.setStrict(properties.getStrict());
        dataSource.setStrategy(properties.getStrategy());
        dataSource.setP6spy(properties.getP6spy());
        dataSource.setSeata(properties.getSeata());
        String primary = "true".equals(this.context.getEnvironment().getProperty("spring.shardingsphere.enabled"))
                ? "sharding-data-source" : properties.getPrimary();
        dataSource.setPrimary(primary);
        log.info("Mrssz Datasource primary: {}", primary);
        return dataSource;
    }
}

同时在

application.yml

配置文件中新增Dynamic数据源

spring:
  application:
    name: readwrite-splitting
  datasource:
    dynamic:
      primary: master
      datasource:
        master:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: 'jdbc:mysql://127.0.0.1:3306/rw_master?characterEncoding=utf-8&useSSL=false'
          password: ***
          type: com.zaxxer.hikari.HikariDataSource
          username: root
          hikari:
            connection-timeout: 30000
            idle-timeout: 600000
            minimum-idle: 10
            maximum-pool-size: 10
    type: com.zaxxer.hikari.HikariDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    hikari:
      pool-name: MrsszHikariCP
      connection-timeout: 30000
      idle-timeout: 600000
      minimum-idle: 10
      maximum-pool-size: 10
      auto-commit: true



3. 启动测试

修改配置后启动项目,能看到控制台打印日志中新增了两个数据源,一个是sharding的sharding-data-source,另一个是dynamic的master。

2022-06-12 23-24-54屏幕截图.png



4. 新增使用Dynamic数据源的方法

后续所有改动都是基于

ShardingSphere-JDBC(5.1.1版本)读写分离示例

做的修改。



4.1 controller层新增方法
    @GetMapping("/queryByMaster")
    public ReadWriteContentEntity getContentByMaster(@RequestParam int id) {
        return readWriteContentService.getContentByMaster(id);
    }


4.2 service层新增方法
    public ReadWriteContentEntity getContentByMaster(int id) {
        return readWriteContentMapper.getContentByMaster(id);
    }


4.3 dao层新增方法

不改动原本的sharding相关方法,写一个新方法标注使用

@DS("master")

数据源,如果该读到的是主库的数据而原sharding读的还是从库的话则说明同时生效了。

    @DS("master")
    ReadWriteContentEntity getContentByMaster(@Param("id") int id);


4.4 mapper层新增方法
    <select id="getContentByMaster" resultType="cn.mrssz.readwritesplitting.entity.ReadWriteContentEntity">
        SELECT * FROM t_content
        WHERE id = #{id}
    </select>



4. 效果测试

原query方法,预期读到从库的数据,正常

2022-06-12 23-52-48屏幕截图.png

新queryByMaster方法,预期读到主库的数据,正常

2022-06-12 23-52-27屏幕截图.png



5 其他

此外,值得注意的是baomidou的DynamicDataSource和ShardingSphere都是支持多数据源的,但是DynamicDataSource的多数据源存在事务异常不能回滚的问题,DynamicDataSource的多数据源方式难以支持跨数据源事务。



版权声明:本文为m0_46216744原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。