捣鼓了大半天… 终于成功了,亲测可用…
注意依赖版本,我这里的spring boot 是2.x的。如果是1.x就不会有后面的那么多事了(就是不乐意用1.x,所以捣鼓了很久)。
mysql
mysql-connector-java
8.0.16
io.shardingjdbc
sharding-jdbc-core
2.0.3
com.dangdang
sharding-jdbc-config-spring
1.5.4.1
com.alibaba
druid-spring-boot-starter
1.1.17
org.springframework.boot
spring-boot-starter-web
2.1.5.RELEASE
一开始,是按照大部分教程,这么配置的
#sharding.jdbc.datasource.ds-master.type=com.alibaba.druid.pool.DruidDataSource
#sharding.jdbc.datasource.ds-master.driver-class-name=com.mysql.jdbc.Driver
#sharding.jdbc.datasource.ds-master.url=jdbc:mysql://xxxxxx:3306/xx?useUnicode=true&characterEncoding=utf8
#sharding.jdbc.datasource.ds-master.username=xx
#sharding.jdbc.datasource.ds-master.password=xx
## 分表配置
#sharding.jdbc.config.sharding.tables.vem_order_info.actual-data-nodes=ds_master.vem_order_info_${0..1}
#sharding.jdbc.config.sharding.tables.vem_order_info.table-strategy.standard.sharding-column=order_sn
#sharding.jdbc.config.sharding.tables.vem_order_info.table-strategy.standard.precise-algorithm-class-name=com.yunzhukj.vending.shardingjdbc.MyPreciseShardingAlgorithm
上面这么配置,加上 自己定义的 MyPreciseShardingAlgorithm这个类,在springboot 1.x确实可用。
public class MyPreciseShardingAlgorithm implements PreciseShardingAlgorithm {
private Logger logger = LoggerFactory.getLogger(MyPreciseShardingAlgorithm.class);
@Override
public String doSharding(Collection collection, PreciseShardingValue preciseShardingValue) {
for (String tableName : collection) {
String value = preciseShardingValue.getValue();
int length = value.length();
if (tableName.endsWith(Integer.parseInt(value.substring(length - 2, length - 1)) % 2 + "")) {
return tableName;
}
}
throw new IllegalArgumentException();
}
}
如果是1.x,你现在自己在数据库里,建两个表vem_order_info_0 和 vem_order_info_1,正常查询,新增,都能实现分表。而且上面依赖中sharding-jdbc-config-spring这个也不需要。
一开始我想上面这么写,然后开始冒出问题了…
问题1:
Description:
The bean ‘dataSource’, defined in class path resource [io/shardingjdbc/spring/boot/SpringBootConfiguration.class], could not be registered. A bean with that name has already been defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class] and overriding is disabled.
Action:
Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
问题2:
Caused by: java.lang.ClassNotFoundException: org.springframework.boot.bind.RelaxedPropertyResolver
问题3:
Failed to configure a DataSource: ‘url’ attribute is not specified and no embedded datasource could be configured.
等等… 冒出各种问题
后来才发现,直接用上面那个配置不行…接下来才是2.x的解决方案…(是的,上面都是废话…)
1、依赖就是一开始发的
2、application.properties
server.port=8080
mybatis-plus.global-config.db-config.column-underline=true
mybatis-plus.mapper-locations=classpath:com/mht/springbootmybatisplus/mapper/xml/*.xml
mybatis-plus.type-aliases-package=com.mht.springbootmybatisplus.entity
sharding.jdbc.max-active=100
sharding.jdbc.url=jdbc:mysql://xxxxxx:3306/xxxxxx?useUnicode=true&characterEncoding=utf8
sharding.jdbc.username=xx
sharding.jdbc.password=xxxxx
sharding.jdbc.driver-class-name=com.mysql.cj.jdbc.Driver
3、新增两个文件 ShardDataSourceProperties (application.properties里sharding.jdbc对应的类) ShardDataSourceConfig(数据源配置,还有分表的配置)
@ConfigurationProperties(prefix = "sharding.jdbc")
public class ShardDataSourceProperties {
private String driverClassName;
private String url;
private String username;
private String password;
private String filters;
private int maxActive;
private int initialSize;
private int maxWait;
private int minIdle;
private int timeBetweenEvictionRunsMillis;
private int minEvictableIdleTimeMillis;
private String validationQuery;
private boolean testWhileIdle;
private boolean testOnBorrow;
private boolean testOnReturn;
private boolean poolPreparedStatements;
private int maxPoolPreparedStatementPerConnectionSize;
private boolean removeAbandoned;
private int removeAbandonedTimeout;
private boolean logAbandoned;
private List connectionInitSqls;
private String connectionProperties;
// 省略get 和set
}
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.yunzhukj.vending.shardingjdbc.UserIdShardingAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@Configuration
@EnableTransactionManagement
@ConditionalOnClass(DruidDataSource.class)
@EnableConfigurationProperties(ShardDataSourceProperties.class)
public class ShardDataSourceConfig {
private final static String order = "vem_order_info";
@Autowired
private ShardDataSourceProperties shardDataSourceProperties;
@Bean
public DataSource dataSource() throws SQLException {
return ShardingDataSourceFactory.createDataSource(shardingRule());
}
private DataSource ds() throws SQLException {
DruidDataSource ds = parentDs();
return ds;
}
private DruidDataSource parentDs() throws SQLException {
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(shardDataSourceProperties.getDriverClassName());
ds.setUrl(shardDataSourceProperties.getUrl());
ds.setUsername(shardDataSourceProperties.getUsername());
ds.setPassword(shardDataSourceProperties.getPassword());
ds.setFilters(shardDataSourceProperties.getFilters());
ds.setMaxActive(shardDataSourceProperties.getMaxActive());
ds.setInitialSize(shardDataSourceProperties.getInitialSize());
ds.setMaxWait(shardDataSourceProperties.getMaxWait());
ds.setMinIdle(shardDataSourceProperties.getMinIdle());
ds.setTimeBetweenEvictionRunsMillis(shardDataSourceProperties.getTimeBetweenEvictionRunsMillis());
ds.setMinEvictableIdleTimeMillis(shardDataSourceProperties.getMinEvictableIdleTimeMillis());
ds.setValidationQuery(shardDataSourceProperties.getValidationQuery());
ds.setTestWhileIdle(shardDataSourceProperties.isTestWhileIdle());
ds.setTestOnBorrow(shardDataSourceProperties.isTestOnBorrow());
ds.setTestOnReturn(shardDataSourceProperties.isTestOnReturn());
ds.setPoolPreparedStatements(shardDataSourceProperties.isPoolPreparedStatements());
ds.setMaxPoolPreparedStatementPerConnectionSize(
shardDataSourceProperties.getMaxPoolPreparedStatementPerConnectionSize());
ds.setRemoveAbandoned(shardDataSourceProperties.isRemoveAbandoned());
ds.setRemoveAbandonedTimeout(shardDataSourceProperties.getRemoveAbandonedTimeout());
ds.setLogAbandoned(shardDataSourceProperties.isLogAbandoned());
ds.setConnectionInitSqls(shardDataSourceProperties.getConnectionInitSqls());
ds.setConnectionProperties(shardDataSourceProperties.getConnectionProperties());
return ds;
}
private DataSourceRule getDataSourceRule() throws SQLException {
Map dataSourceMap = new HashMap<>(2);
dataSourceMap.put("ds", ds());
DataSourceRule dataSourceRule = new DataSourceRule(dataSourceMap);
return dataSourceRule;
}
private TableRule getOrderTableRule() throws SQLException {
String[] uns = new String[2];
for (int i = 0; i < 2; i++) {
uns[i] = order.concat("_").concat(String.valueOf(i));
}
TableRule tableRule = TableRule.builder(order)
.actualTables(Arrays.asList(uns))
.dataSourceRule(getDataSourceRule())
.tableShardingStrategy(new TableShardingStrategy("order_sn", new OrderShardingAlgorithm()))
.build();
return tableRule;
}
private ShardingRule shardingRule() throws SQLException {
ShardingRule shardingRule = ShardingRule.builder()
.dataSourceRule(getDataSourceRule())
.tableRules(Arrays.asList(getOrderTableRule())).build();
return shardingRule;
}
}
4、OrderShardingAlgorithm 分表策略
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 java.util.Collection;
import java.util.LinkedHashSet;
public class OrderShardingAlgorithm implements SingleKeyTableShardingAlgorithm {
@Override
public String doEqualSharding(Collection tableNames, ShardingValue shardingValue) {
for (String each : tableNames) {
if (each.endsWith(shardingValue.getValue()%2+"")) {
return each;
}
}
throw new IllegalArgumentException();
}
@Override
public Collection doInSharding(Collection tableNames, ShardingValue shardingValue) {
Collection result = new LinkedHashSet<>(tableNames.size());
for (Integer value : shardingValue.getValues()) {
for (String tableName : tableNames) {
if (tableName.endsWith(value%2+"")) {
result.add(tableName);
}
}
}
return result;
}
@Override
public Collection doBetweenSharding(Collection tableNames, ShardingValue shardingValue) {
Collection result = new LinkedHashSet<>(tableNames.size());
Range range = shardingValue.getValueRange();
for (Integer i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) {
for (String each : tableNames) {
if (each.endsWith(i%2+"")) {
result.add(each);
}
}
}
return result;
}
}
ok,这么写就行了… 成功解决问题。
解决方案出处:https://www.cnblogs.com/EchoXian/p/9732777.html 在此特别感谢。
上面贴了很多错误信息,其实是为了大家搜索这些错误的时候能找到我这篇文章,本人为了捣鼓这个,花了大半天,希望大家早点看到,节约时间。
另外,如果有帮助,给我点个赞呗(不要脸),嘻嘻。