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。
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方法,预期读到从库的数据,正常
新queryByMaster方法,预期读到主库的数据,正常
5 其他
此外,值得注意的是baomidou的DynamicDataSource和ShardingSphere都是支持多数据源的,但是DynamicDataSource的多数据源存在事务异常不能回滚的问题,DynamicDataSource的多数据源方式难以支持跨数据源事务。