导入依赖
<!-- dynamic-datasource 多数据源 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
<!-- shardingsphere -->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.1.1</version>
</dependency>
配置yml
spring:
shardingsphere:
# 展示修改以后的sql语句
props:
sql.show: true
datasource:
names: ds0
ds0:
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
jdbc-url: jdbc:mysql://39.98.91.88:443/test?allowMultiQueries=true
username:
password:
#jdbc-url: jdbc:mysql://localhost:3306/dev?serverTimezone=UTC&characterEncoding=UTF-8
#username: root
#password:
sharding:
## 默认数据源
default-data-source-name: ds0
tables:
user_order:
actual-data-nodes: ds0.user_order_$->{0..5}
table-strategy:
inline:
sharding-column: user_mark
algorithm-expression: user_order_$->{Math.abs(user_mark.hashCode()) % 6}
order_detail:
actual-data-nodes: ds0.order_detail_$->{0..5}
table-strategy:
inline:
sharding-column: order_id
algorithm-expression: order_detail_$->{Math.abs(order_id.hashCode()) % 6}
keyGenerator: # 指定表的主键生成策略为SNOWFLAKE
type: SNOWFLAKE #主键生成策略为SNOWFLAKE
column: id #指定主键
order_item_info:
actual-data-nodes: ds0.order_item_info_$->{0..5}
table-strategy:
inline:
sharding-column: order_id
algorithm-expression: order_item_info_$->{Math.abs(order_id.hashCode()) % 6}
keyGenerator:
type: SNOWFLAKE
column: id
order_jd_waybill:
actual-data-nodes: ds0.order_jd_waybill_$->{0..5}
table-strategy:
inline:
sharding-column: id
algorithm-expression: order_jd_waybill_$->{id % 6}
keyGenerator: # 指定表的主键生成策略为SNOWFLAKE
type: SNOWFLAKE #主键生成策略为SNOWFLAKE
column: id #指定主键
order_third_waybill:
actual-data-nodes: ds0.order_third_waybill_$->{0..5}
table-strategy:
inline:
sharding-column: id
algorithm-expression: order_third_waybill_$->{id % 6}
keyGenerator: # 指定表的主键生成策略为SNOWFLAKE
type: SNOWFLAKE #主键生成策略为SNOWFLAKE
column: id #指定主键
# 设置绑定表,左边的为主表,右边的为子表,可以配置多个,用集合的方式
binding-tables:
- order_detail,order_item_info
# 动态数据源配置
datasource:
dynamic:
datasource:
master:
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
url: jdbc:mysql://39.98.91.88:443/test?allowMultiQueries=true
username:
password:
#url: jdbc:mysql://localhost:3306/dev?serverTimezone=UTC&characterEncoding=UTF-8
#username: root
#password:
# 指定默认数据源名称
primary: master
config配置文件
import cn.nascent.jdm.common.constant.common.DataSouceConstant;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.provider.AbstractDataSourceProvider;
import com.baomidou.dynamic.datasource.provider.DynamicDataSourceProvider;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
/**
* 数据源配置
* 使用dynamic-datasource与shardingshpere-jdbc结合,需要分片的表单独交给shardingsphere处理,
* 再经由dynamic-datasource管理,弥补shardingsphere在sql上的不支持项(union等)
*
* @author
* @since
*/
@Configuration
@AutoConfigureBefore({DynamicDataSourceAutoConfiguration.class, SpringBootConfiguration.class})
public class MyDataSourceConfiguration {
@Resource
private DynamicDataSourceProperties properties;
/**
* 未使用分片, 脱敏的名称(默认): shardingDataSource
* 使用了主从: masterSlaveDataSource
* 根据自己场景修改注入
*/
@Resource(name = "shardingDataSource")
@Lazy
DataSource shardingDataSource;
@Bean
public DynamicDataSourceProvider dynamicDataSourceProvider() {
return new AbstractDataSourceProvider() {
@Override
public Map<String, DataSource> loadDataSources() {
Map<String, DataSource> dataSourceMap = new HashMap<>(16);
// 将sharding的数据源交给dynamic管理,数据源名字自定义
dataSourceMap.put(DataSouceConstant.SHARDING_SPHERE, shardingDataSource);
//打开下面的代码可以把 shardingJdbc 内部管理的子数据源也同时添加到动态数据源里 (根据自己需要选择开启)
// dataSourceMap.putAll(((ShardingSphereDataSource) shardingDataSource).getDataSourceMap());
return dataSourceMap;
}
};
}
/**
* 将动态数据源设置为首选的
* 当spring存在多个数据源时, 自动注入的是首选的对象
* 设置为主要的数据源之后,就可以支持shardingjdbc原生的配置方式了
* 3.4.0版本及以上使用以下方式注入,老版本请阅读文档 进阶-手动注入多数据源
*/
@Primary
@Bean
public DataSource dataSource() {
DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();
dataSource.setPrimary(properties.getPrimary());
dataSource.setStrict(properties.getStrict());
dataSource.setStrategy(properties.getStrategy());
dataSource.setP6spy(properties.getP6spy());
dataSource.setSeata(properties.getSeata());
return dataSource;
}
}
调用数据源
- 使用@DS注解切换数据源,@DS可以作用在接口实现类上,也可以作用在方法上,作用在mapper等无效,注意如果B方法被A方法调用,且A开启了事务,则B方法想切换数据源一定要添加新事务
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
,如果B开启新事务,B会被A事务覆盖,导致B无法切换数据源,参考文章:点我跳转到新文章,正确使用如下: @DS(value = DataSouceConstant.SHARDING_SPHERE)
注解的值填Config配置中数据源的值,这个值是自己自定义的【dataSourceMap.put(DataSouceConstant.SHARDING_SPHERE, shardingDataSource)
】。
A方法:
@Transactional(rollbackFor = Exception.class)
@Override
public Boolean orderSyncJob(String masterId) {
// 更新数据
orderDetailService.saveOrUpdateOrderDetailList(popOrderDetailDTOList);
}
B方法
@Override
@DS(value = DataSouceConstant.SHARDING_SPHERE)
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public boolean saveOrUpdateOrderDetailList(List<PopOrderDetailDTO> popOrderDetailDTOList) {
if (CollectionUtil.isNotEmpty(popOrderDetailDTOList)) {
this.getBaseMapper().insertOrUpdateBatchOrder(BeanConversionUtils.beanListConversion(popOrderDetailDTOList, OrderDetailDO.class));
}
return true;
}