<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1.tmp</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.12</version>
</dependency>
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>sharding-jdbc-config-spring</artifactId>
<version>1.5.4.1</version>
</dependency>
CREATE DATABASE `xjf_0` CHARACTER SET 'utf8' COLLATE 'utf8_general_ci'
CREATE DATABASE `xjf_1` CHARACTER SET 'utf8' COLLATE 'utf8_general_ci'
CREATE TABLE `user_0` (
`id` BIGINT(64) NOT NULL,
`city` VARCHAR(20) NOT NULL,
`name` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
CREATE TABLE `user_1` (
`id` BIGINT(64) NOT NULL,
`city` VARCHAR(20) NOT NULL,
`name` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:rdb="http://www.dangdang.com/schema/ddframe/rdb"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.dangdang.com/schema/ddframe/rdb
http://www.dangdang.com/schema/ddframe/rdb/rdb.xsd
">
<!--======================================================分库分表===开始=================================================-->
<!-- inline 表达式报错解决:在 Spring 的配置文件中,由于 inline 表达式使用了 Groovy 语法, Groovy 语法的变量符与 Spring 默认占位符
同为 ${} ,因此需要在配置文件中增加下面这行来解决解析报错问题-->
<context:property-placeholder ignore-unresolvable="true" />
<!-- 第一个数据库 -->
<bean id="ds_0" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close" primary="true">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/xjf_0?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&useSSL=false" />
<property name="username" value="root" />
<property name="password" value="123456" />
</bean>
<!-- 第二个数据库 -->
<bean id="ds_1" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/xjf_1?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&useSSL=false" />
<property name="username" value="root" />
<property name="password" value="123456" />
</bean>
<!-- 配置分库规则: 根据 city 来分库,同一个城市的数据存同一个数据库中 -->
<rdb:strategy id="databaseShardingStrategy" sharding-columns="city"
algorithm-class="com.xjf.sharding.algorithm.MySingleKeyDbShardingAlgorithm" />
<!-- 配置分表规则 -->
<rdb:strategy id="tableShardingStrategy" sharding-columns="id"
algorithm-class="com.xjf.sharding.algorithm.MyUserSingleKeyTableShardingAlgorithm" />
<!-- 配置分库分表数据源 -->
<rdb:data-source id="dataSource">
<rdb:sharding-rule data-sources="ds_0, ds_1">
<rdb:table-rules>
<rdb:table-rule logic-table="user" actual-tables="user_${0..1}"
database-strategy="databaseShardingStrategy" table-strategy="tableShardingStrategy">
<!-- 使用 Sharding-JDBC 的默认 ID 生成器,基于雪花算法。-->
<rdb:generate-key-column column-name="id" />
</rdb:table-rule>
</rdb:table-rules>
</rdb:sharding-rule>
</rdb:data-source>
<!--======================================================分库分表===结束=================================================-->
<!-- 给 MyBatis-Plus 配置数据源 -->
<bean id="mybatisSqlSessionFactoryBean" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
@ImportResource(locations = "classpath:sharding.xml")
@MapperScan("com.xjf.sharding.mapper")
@SpringBootApplication
public class ShardingApplication {
public static void main(String[] args) {
SpringApplication.run(ShardingApplication.class, args);
}
}
public class MySingleKeyDbShardingAlgorithm implements SingleKeyDatabaseShardingAlgorithm<String> {
private static Map<String, List<String>> shardingMap = new ConcurrentHashMap<>();
static {
shardingMap.put("ds_0", Arrays.asList("上海"));
shardingMap.put("ds_1", Arrays.asList("杭州"));
}
@Override
public String doEqualSharding(Collection<String> collection, ShardingValue<String> shardingValue) {
for (String each : collection) {
System.err.println("数据库:" + each);
System.err.println("添加数据的城市:" + shardingValue.getValue());
if (shardingMap.get(each).contains(shardingValue.getValue())){
return each;
}
}
// 默认保存在数据库 "ds_0" 中
return "ds_0";
}
@Override
public Collection<String> doInSharding(Collection<String> collection, ShardingValue<String> shardingValue) {
Collection<String> result = new LinkedHashSet<>(collection.size());
for (String each : collection) {
if (shardingMap.get(each).contains(shardingValue.getValue())){
result.add(each);
}else {
result.add("ds_0");
}
}
return result;
}
@Override
public Collection<String> doBetweenSharding(Collection<String> collection, ShardingValue<String> shardingValue) {
Collection<String> result = new LinkedHashSet<>(collection.size());
for (String each : collection) {
if (shardingMap.get(each).contains(shardingValue.getValue())){
result.add(each);
}else {
result.add("ds_0");
}
}
return result;
}
}
public class MyUserSingleKeyTableShardingAlgorithm implements SingleKeyTableShardingAlgorithm<Long> {
/**
* 在 where 使用 = 作为条件分片键
*/
@Override
public String doEqualSharding(Collection<String> collection, ShardingValue<Long> shardingValue) {
System.err.println("运行方法: doEqualSharding");
for (String each : collection) {
System.err.println("表:" + each);
System.err.println("shardingValue.getValue: " + shardingValue.getValue());
// 配合测试分库分表,取模是只有 2 张表。在测试不分库只分表时是 4 张表。分别对应使用
// if (each.endsWith(shardingValue.getValue() % 4 +"")){
if (each.endsWith(shardingValue.getValue() % 2 +"")){
return each;
}
}
throw new IllegalArgumentException();
}
/**
* 在 where 使用 in 作为条件分片键
*/
@Override
public Collection<String> doInSharding(Collection<String> collection, ShardingValue<Long> shardingValue) {
System.err.println("运行方法: doInSharding");
Collection<String> result = new LinkedHashSet<>(collection.size());
for (Long value : shardingValue.getValues()) {
for (String tableName : collection) {
if (tableName.endsWith(value % 4 + "")){
result.add(tableName);
}
}
}
return result;
}
/**
* 在 where 使用 between 作为条件分片键
*/
@Override
public Collection<String> doBetweenSharding(Collection<String> collection, ShardingValue<Long> shardingValue) {
System.err.println("运行方法: doBetweenSharding");
Collection<String> result = new LinkedHashSet<>(collection.size());
Range<Long> range = shardingValue.getValueRange();
for (Long i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) {
for (String each : collection) {
if (each.endsWith( i % 4 + "")){
result.add(each);
}
}
}
return result;
}
}
@GetMapping("/add3")
public String add3(){
for (int i = 0; i < 100; i++) {
User user = new User();
// 不设置 ID,在 sharding.xml 配置了 Sharding-JDBC 的默认分布式主键生成,是采用雪花算法实现的。
// 在类 com.dangdang.ddframe.rdb.sharding.keygen.DefaultKeyGenerator 中
// user.setId(Long.valueOf(i));
// 随机设置城市
int random = new Random().nextInt();
if (random % 2 == 0){
user.setCity("上海");
}else {
user.setCity("杭州");
}
user.setName("嘉文四世");
userMapper.insert(user);
}
return "success";
}
看《Spring Cloud微服务入门、实战与进阶》