本文介绍 spring boot 2.1 与 dangdang 分表插件进行整合
当前项目使用的是 jpa 与 durid
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>sharding-jdbc-core</artifactId>
<version>1.5.4.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.9</version>
</dependency>
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false
spring.datasource.databaseName=monitor_image
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
项目的需求是按照日期分表,一天一个,已下划线加当天的日期,例如:test_20190620、test_20190621
package com.truthso.monitor.sharding;
import com.dangdang.ddframe.rdb.sharding.api.ShardingValue;
import com.dangdang.ddframe.rdb.sharding.api.strategy.table.SingleKeyTableShardingAlgorithm;
import com.google.common.collect.Range;
import com.truthso.monitor.utils.DateUtil;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedHashSet;
/**
* 日期分表
*/
public class DateShardingAlgorithm implements SingleKeyTableShardingAlgorithm<String> {
@Override
public String doEqualSharding(Collection<String> availableTargetNames, ShardingValue<String> shardingValue) {
String logicTableName = shardingValue.getLogicTableName();
String date = shardingValue.getValue();
return String.format("%s_%s", logicTableName, date);
}
@Override
public Collection<String> doInSharding(Collection<String> availableTargetNames, ShardingValue<String> shardingValue) {
String logicTableName = shardingValue.getLogicTableName();
Date today = new Date();
Collection<String> result = new LinkedHashSet<>(availableTargetNames.size());
for (String date : shardingValue.getValues()) {
Date day = DateUtil.str2Date(date, DateUtil.PATTERN_DATE_SHORT);
if (day.after(today)) {
continue;
}
result.add(String.format("%s_%s", logicTableName, date));
}
return result;
}
@Override
public Collection<String> doBetweenSharding(Collection<String> availableTargetNames, ShardingValue<String> shardingValue) {
String logicTableName = shardingValue.getLogicTableName();
Range<String> range = shardingValue.getValueRange();
String lower = range.lowerEndpoint();
String upper = range.upperEndpoint();
Date start = DateUtil.str2Date(lower, DateUtil.PATTERN_DATE_SHORT);
Date end = DateUtil.str2Date(upper, DateUtil.PATTERN_DATE_SHORT);
Date today = new Date();
if (end.after(today)) {
end = today;
upper = DateUtil.formatDate(DateUtil.PATTERN_DATE_SHORT);
}
LinkedHashSet<String> result = new LinkedHashSet<>(availableTargetNames.size());
result.add(String.format("%s_%s", logicTableName, lower));
while (start.before(end)) {
String day = DateUtil.date2Str(start, DateUtil.PATTERN_DATE_SHORT);
result.add(String.format("%s_%s", logicTableName, day));
start = DateUtil.addDate(start, 1);
}
result.add(String.format("%s_%s", logicTableName, upper));
return result;
}
}
DateUtil.PATTERN_DATE_SHORT) 就是 yyyyMMdd 的格式
另外需要增加congfig来加载我们的分表策略
package com.truthso.monitor.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.dangdang.ddframe.rdb.sharding.api.ShardingDataSourceFactory;
import com.dangdang.ddframe.rdb.sharding.api.rule.DataSourceRule;
import com.dangdang.ddframe.rdb.sharding.api.rule.ShardingRule;
import com.dangdang.ddframe.rdb.sharding.api.rule.TableRule;
import com.dangdang.ddframe.rdb.sharding.api.strategy.table.TableShardingStrategy;
import com.mysql.cj.jdbc.Driver;
import com.truthso.monitor.sharding.DateShardingAlgorithm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class DataSourceConfiguration {
@Value("${spring.datasource.url}")
private String url;
@Value("${spring.datasource.username}")
private String username;
@Value("${spring.datasource.password}")
private String password;
@Bean
public DataSource getDataSource() throws SQLException {
return buildDataSource();
}
private DataSource buildDataSource() throws SQLException {
Map<String, DataSource> dsMap = new HashMap<>();
DataSource ds = createDataSource(url, username, password);
dsMap.put("druid", ds);
DataSourceRule dataSourceRule = new DataSourceRule(dsMap);
// 这里写入的就是具体的表的前缀
TableRule monitorResultRule = TableRule.builder("image_old_compare")
.dataSourceRule(dataSourceRule)
.dynamic(true)
.tableShardingStrategy(new TableShardingStrategy("datestr", new DateShardingAlgorithm()))
.build();
ShardingRule shardingRule = ShardingRule.builder()
.dataSourceRule(dataSourceRule)
.tableRules(Arrays.asList(monitorResultRule))
.build();
DataSource dataSource = ShardingDataSourceFactory.createDataSource(shardingRule);
return dataSource;
}
private static DataSource createDataSource(final String dataSourceName, final String username, final String password) {
DruidDataSource result = new DruidDataSource();
result.setDriverClassName(Driver.class.getName());
result.setUrl(dataSourceName);
result.setUsername(username);
result.setPassword(password);
return result;
}
}
重要的地方 就是分表的字段,比如我日期分表的字段就是 datastr,所有的表都是一样的结构,但是不同的每个表的datestr字段都是当前表的后缀,比如分表 test_20190603 那么 这个表的 datestr 字段的值都是 20190603 不然会查询不出来。
就正常使用的方式就行,比如添加
ImageOldCompare compare = new ImageOldCompare();
compare.setSamplePageUrl(samplePageUrl);
compare.setSampleImageUrl(sampleImageUrl);
compare.setSim(sim);
compare.setResultImageUrl(urls[0]);
compare.setResultPageUrl(pageUrl);
compare.setResultImageSource(resultInfo.source);
compare.setDatestr(DateUtil.date2Str(new Date(), DateUtil.PATTERN_DATE_SHORT));
dao.save(compare);
注意 每次的操作,datestr 字段都需要设置要操作的表的日期,不然会报错。其余所有的操作和不分表的操作一样,包括分页之类的。