版本号:
jeecgboot 3.0
sharding-jdbc-spring-boot-starter 4.1.0
- 引入依赖
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.1.0</version>
</dependency>
2.yaml配置文件,如果用properties可以在线转换一下www.toyaml.com/index.html
spring:
shardingsphere:
datasource:
b0:
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://localhost:3306/peoples_congress?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
username: safety
password: 0z@rBlFarp#r9#yZ
b1:
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://localhost:3306/peoples_congress?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
username: safety
password: 0z@rBlFarp#r9#yZ
names: b0,b1
sharding:
default-data-source-name: b0
tables:
location:
actual-data-nodes: b$->{0..1}.location_$->{2022}$->{1..12}
database-strategy:
standard:
precise-algorithm-class-name: org.jeecg.modules.sharding.algorithm.DBShardingAlgorithm
sharding-column: status
key-generator:
column: status
props:
worker:
id: 123
type: SNOWFLAKE
table-strategy:
standard:
precise-algorithm-class-name: org.jeecg.modules.sharding.algorithm.TableShardingAlgorithm
sharding-column: device_time
3.application.yaml
spring:
application:
name: jeecg-system
profiles:
active: test,sharding
4.添加配置类
在config目录下,添加配置类DataSourceConfiguration和DataSourceHealthConfig
其中DataSourceConfiguration.java配置类代码如下:
package org.jeecg.config.sharding;
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.DataSourceProperty;
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.Map;
/**
* 分库分表数据源配置
* @author lisong
*/
@Configuration
@AutoConfigureBefore({DynamicDataSourceAutoConfiguration.class, SpringBootConfiguration.class})
public class DataSourceConfiguration {
/**
* 分表数据源名称
*/
public static final String SHARDING_DATA_SOURCE_NAME = "sharding";
/**
* 动态数据源配置项
*/
@Resource
private DynamicDataSourceProperties dynamicDataSourceProperties;
@Lazy
@Resource
DataSource shardingDataSource;
/**
* 将shardingDataSource放到了多数据源(dataSourceMap)中
* 注意有个版本的bug,3.1.1版本 不会进入loadDataSources 方法,这样就一直造成数据源注册失败
*/
@Bean
public DynamicDataSourceProvider dynamicDataSourceProvider() {
Map<String, DataSourceProperty> datasourceMap = dynamicDataSourceProperties.getDatasource();
return new AbstractDataSourceProvider() {
@Override
public Map<String, DataSource> loadDataSources() {
Map<String, DataSource> dataSourceMap = createDataSourceMap(datasourceMap);
// 将 shardingjdbc 管理的数据源也交给动态数据源管理
dataSourceMap.put(SHARDING_DATA_SOURCE_NAME, shardingDataSource);
return dataSourceMap;
}
};
}
/**
* 将动态数据源设置为首选的
* 当spring存在多个数据源时, 自动注入的是首选的对象
* 设置为主要的数据源之后,就可以支持shardingjdbc原生的配置方式了
*
* @return
*/
@Primary
@Bean
public DataSource dataSource(DynamicDataSourceProvider dynamicDataSourceProvider) {
DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();
dataSource.setPrimary(dynamicDataSourceProperties.getPrimary());
dataSource.setStrict(dynamicDataSourceProperties.getStrict());
dataSource.setStrategy(dynamicDataSourceProperties.getStrategy());
dataSource.setProvider(dynamicDataSourceProvider);
dataSource.setP6spy(dynamicDataSourceProperties.getP6spy());
dataSource.setSeata(dynamicDataSourceProperties.getSeata());
return dataSource;
}
}
DataSourceHealthConfig.java配置类代码如下:
package org.jeecg.config.sharding;
import org.apache.shiro.util.StringUtils;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.actuate.autoconfigure.jdbc.DataSourceHealthContributorAutoConfiguration;
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
import org.springframework.boot.actuate.jdbc.DataSourceHealthIndicator;
import org.springframework.boot.jdbc.metadata.DataSourcePoolMetadataProvider;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.util.Map;
@Configuration
public class DataSourceHealthConfig extends DataSourceHealthContributorAutoConfiguration {
@Value("${spring.datasource.dbcp2.validation-query:select 1}")
private String defaultQuery;
public DataSourceHealthConfig(Map<String, DataSource> dataSources, ObjectProvider<DataSourcePoolMetadataProvider> metadataProviders) {
super(dataSources, metadataProviders);
}
@Override
protected AbstractHealthIndicator createIndicator(DataSource source) {
DataSourceHealthIndicator indicator = (DataSourceHealthIndicator) super.createIndicator(source);
if (!StringUtils.hasText(indicator.getQuery())) {
indicator.setQuery(defaultQuery);
}
return indicator;
}
}
- 开发分库分表的业务逻辑 DBShardingAlgorithm 分库业务逻辑
package org.jeecg.modules.sharding.algorithm;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
import java.util.Collection;
@Slf4j
public class DBShardingAlgorithm implements PreciseShardingAlgorithm<Integer> {
@Override
public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Integer> shardingValue) {
System.out.println("DB PreciseShardingAlgorithm ");
// 真实节点
availableTargetNames.stream().forEach((item) -> {
log.info("actual node db:{}", item);
});
log.info("logic table name:{},rout column:{}", shardingValue.getLogicTableName(), shardingValue.getColumnName());
//精确分片
log.info("column value:{}", shardingValue.getValue());
int orderId = shardingValue.getValue();
int db_index = orderId & (2 - 1);
for (String each : availableTargetNames) {
if (each.equals("b"+db_index)) {
return each;
}
}
throw new IllegalArgumentException();
}
}
TableShardingAlgorithm 分表业务逻辑
package org.jeecg.modules.sharding.algorithm;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
import java.util.Collection;
import java.util.Date;
@Slf4j
public class TableShardingAlgorithm implements PreciseShardingAlgorithm<Date> {
@Override
public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Date> shardingValue) {
System.out.println("table PreciseShardingAlgorithm ");
// 真实节点
availableTargetNames.stream().forEach((item) -> {
log.info("actual node table:{}", item);
});
log.info("logic table name:{},rout column:{}", shardingValue.getLogicTableName(), shardingValue.getColumnName());
//精确分片
log.info("column value:{}", shardingValue.getValue());
String tb_name = shardingValue.getLogicTableName() + "_";
// 根据当前日期 来 分库分表
Date date = shardingValue.getValue();
String year = String.format("%tY", date);
String mon =String.valueOf(Integer.parseInt(String.format("%tm", date))); // 去掉前缀0
String dat = String.format("%td", date);
if(Integer.parseInt(mon) < 10){
mon = "0"+mon;
}
// 选择表
tb_name = tb_name + year + mon;
System.out.println("tb_name:" + tb_name);
for (String each : availableTargetNames) {
if (each.equals(tb_name)) {
return each;
}
}
throw new IllegalArgumentException();
}
}
6.开发业务代码逻辑,需要注意切换数据源,将数据源切换到sharding上