1 数据库创建语句:
//后缀要为1,前面什么都无所谓,因为后期要用这个判断存入那哪数据库
CREATE DATABASE master04091
CREATE TABLE tab_user0(
id INT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY,
NAME VARCHAR(30) NOT NULL,
age INT(10) NOT NULL,
create_time DATETIME
)
CREATE TABLE tab_user1(
id INT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY,
NAME VARCHAR(30) NOT NULL,
age INT(10) NOT NULL,
create_time DATETIME
)
CREATE TABLE tab_user2(
id INT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY,
NAME VARCHAR(30) NOT NULL,
age INT(10) NOT NULL,
create_time DATETIME
)
CREATE TABLE tab_user3(
id INT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY,
NAME VARCHAR(30) NOT NULL,
age INT(10) NOT NULL,
create_time DATETIME
)
CREATE TABLE tab_user4(
id INT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY,
NAME VARCHAR(30) NOT NULL,
age INT(10) NOT NULL,
create_time DATETIME
)
//之后再创建一个库名为 master04092,后缀要是2,前面什么都无所谓,因为后期要用这个判断存入那哪数据库,库中同样要有这5个表。
1.8
1.8
1.8
2.1.3.RELEASE
1.18.8
4.12
org.springframework.boot
spring-boot-starter-web
${springframework.boot.version}
org.springframework.boot
spring-boot-starter-test
${springframework.boot.version}
test
org.springframework.boot
spring-boot-test
${springframework.boot.version}
test
junit
junit
${junit.version}
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.0.1
org.apache.shardingsphere
sharding-jdbc-spring-boot-starter
4.0.0-RC1
org.apache.commons
commons-lang3
3.4
mysql
mysql-connector-java
5.1.38
org.projectlombok
lombok
${lombok.version}
(2):配置文件 application.peoperties
server.port=8082
#控制台打印sql
spring.shardingsphere.props.sql.show=true
spring.main.allow-bean-definition-overriding=true
#数据源 先创建2个数据库
spring.shardingsphere.datasource.names=master04091,master04092
# 配置master04091
spring.shardingsphere.datasource.master04091.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.master04091.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.master04091.jdbc-url=jdbc:mysql://localhost:3306/master04091?characterEncoding=utf-8&&serverTimezone=GMT%2B8
spring.shardingsphere.datasource.master04091.username=root
spring.shardingsphere.datasource.master04091.password=1234
# 配置master04092
spring.shardingsphere.datasource.master04092.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.master04092.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.master04092.jdbc-url=jdbc:mysql://localhost:3306/master04092?characterEncoding=utf-8&&serverTimezone=GMT%2B8
spring.shardingsphere.datasource.master04092.username=root
spring.shardingsphere.datasource.master04092.password=1234
# 配置进行分库的字段
spring.shardingsphere.sharding.default-database-strategy.standard.sharding-column=create_time
# 具体的配置规则我们会在自定义类中指定,也就是这个PreciseModuloDatabaseShardingAlgorithm类,这写自定义类路径
spring.shardingsphere.sharding.default-database-strategy.standard.precise-algorithm-class-name=com.util.PreciseModuloDatabaseShardingAlgorithm
# 配置库与表结合,就是你有几个库,几个表,例如:我有master04091和mater04092这2个库,每个库下有五张表,tab_user0......tab_user4,并且指定了逻辑库为master0409,逻辑表为tab_user
spring.shardingsphere.sharding.tables.tab_user.actual-data-nodes=master0409$->{1..2}.tab_user$->{0..4}
# 配置进行分表的字段
spring.shardingsphere.sharding.default-table-strategy.standard.sharding-column=create_time
# 具体的配置规则我们会在自定义类中指定,也就是这个PreciseModuloTableShardingAlgorithm类,这写自定义类路径
spring.shardingsphere.sharding.default-table-strategy.standard.precise-algorithm-class-name=com.util.PreciseModuloTableShardingAlgorithm
(3)实体类:
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name ;
private int age;
//保证给到数据库的时间是date类型,显示到前台的时间是字符串类型
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private String create_time;
}
(4)mapper和service层
//mapper
import com.bean.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
import java.util.Date;
import java.util.List;
@Repository
public interface UserMa {
/**
* 添加,只需向逻辑表中添加即可,
*/
@Insert({
" INSERT INTO tab_user (id,name,age,create_time) ",
" VALUES ( " ,
"#{id,jdbcType=INTEGER}, ",
"#{name,jdbcType=VARCHAR}, ",
"#{age,jdbcType=INTEGER}, ",
"#{create_time,jdbcType=VARCHAR})"
})
int addUser(@Param("id") Integer id,
@Param("name") String name,
@Param("age") Integer age,
@Param("create_time") String create_time);
}
//service接口
import com.bean.User;
import com.util.ResponseUser;
public interface UserSer {
ResponseUser addUser(User user);
}
//service实现
import com.bean.User;
import com.mapper.UserMa;
import com.service.imp.UserSer;
import com.util.ResponseUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserSerDao implements UserSer {
@Autowired
private ResponseUser resUser;
@Autowired
private UserMa userMa;
@Override
public ResponseUser addUser(User user) {
int count=userMa.addUser(
user.getId(),user.getName(),user.getAge(),user.getCreate_time());
if(count==0)
resUser.setAll(1,"添加失败",null);
else
resUser.setAll(0,"添加成功",count);
return resUser;
}
}
(5)自定义规则类
//分库的自定义类
package com.util;
import org.apache.commons.lang3.StringUtils;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
//实现自定义接口
public class PreciseModuloDatabaseShardingAlgorithm
implements PreciseShardingAlgorithm {
/**
* @param collection 存放的是所有的库的列表,这里代表master04091,master04092
* master04091(2020~2024),master04092(2025~2029)
* @return 将数据写入的哪个库
*/
@Override
public String doSharding(Collection collection,
PreciseShardingValue pre) {
try {
//配置的分库分片的sharding-column对应的值,也就是具体时间
String str=pre.getValue());
if (str.isEmpty()) {
throw new UnsupportedOperationException("pre is null");
}
//each为每个库的名字
for (String each:collection) {
//得到具体年,截取字符串要头不要尾
String value=StringUtils.substring(str,0,4);
//以5年为一个库,例如:2020~2024
int c=Integer.parseInt(value)-2020;
//算差值,拿当前时间减去2020,用差除于5,会得到小数,用int强转,只要整数,这样为0的就放到1库,为1的就放到2库
int database_hou_zhui=c/5;//0.2(2021年放到1库),1.2(2026年放到2库)
if(each.endsWith(Integer.toString(database_hou_zhui+1))){
//扔到后缀是database_hou_zhui+1的库,判断当前这个库是否符合我条件,
// 而不是我去找符合我条件的库,因为没法找,好多库呢
return each;
}
}
}catch(ParseException e){
e.printStackTrace();
}
return null;
}
}
//分表的自定义规则类
package com.util;
import org.apache.commons.lang3.StringUtils;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
import java.util.Collection;
/**
* 分表策略,每5年放到一个库中,库中一年一个表
*/
public class PreciseModuloTableShardingAlgorithm
implements PreciseShardingAlgorithm {
@Override
public String doSharding(Collection collection,
PreciseShardingValue prec) {
//对于库的分片collection存放的是所有的库的列表,这里代表master04091,master04092
//配置的分片的sharding-column对应的值
String timeValue = prec.getValue();
//判断timeValue是否为空
if(StringUtils.isBlank(timeValue)){
throw new UnsupportedOperationException("prec is null");
}
//按年路由,一个库中有5年的数据,在库中我们将每年分成一个表,
// 对5取余,判断得到的所有表名后缀是否与取余一致,一致就返回
for (String each:collection) {
//得到具体年,截取字符串要头不要尾
String value=StringUtils.substring(timeValue,0,4);
int c=Integer.parseInt(value);
//循环每个库,看哪个库与当前条件匹配
if(each.endsWith(Integer.toString(c%5))){
return each;
}
}
return null;
}
}
(6) 控制类
import com.bean.User;
import com.service.UserSerDao;
import com.util.ResponseUser;
import com.util.ToolUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
import java.util.Date;
@RestController
public class UserCon {
@Autowired
private UserSerDao userSer;
@Autowired
private ResponseUser responseUser;
/**
* 模拟插入数据
*/
User userList = new User();
/**
* 初始化插入数据,@PostConstruct这个注解代表类实施事就执行这个方法,类似于构造函数(仅仅是我的理解)
*/
@PostConstruct
private void getData() {
SimpleDateFormat sfEnd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
userList=new User(3,"dadada", 298,"2025-05-15 14:39:18");//会发现被存入第二个库中tab_user0表中
//userList=new User(3,"dadada", 298,sfEnd.format(new Date()));当前时间2020年,会发现被存入第一个库中tab_user0表中
System.out.println("测试~"+userList.getCreate_time());
}
/**
* 添加数据,
*/
@GetMapping("/save-user")
public Object saveUser() {
return userSer.addUser(userList);
}
3 完成
访问 http://localhost:8082/save-user
,即可添加数据。结果如下:
总结,
1)如果是普通的按照id取模,年纪取模,直接可以在application文件中指定,例如:
#按照id对2取模 分库
spring.shardingsphere.sharding.default-database-strategy.inline.sharding-column=id
spring.shardingsphere.sharding.default-database-strategy.inline.algorithm-expression=master0409$->{id % 2}
#按照年龄对2取模 分表
spring.shardingsphere.sharding.tables.tab_user.actual-data-nodes=master0409$->{0..1}.tab_user$->{0..1}
spring.shardingsphere.sharding.tables.tab_user.table-strategy.inline.sharding-column=age
spring.shardingsphere.sharding.tables.tab_user.table-strategy.inline.algorithm-expression=tab_user$->{age % 2}
2)如果需要自定义规则控制分库分表,则需要在application文件中指定规则类的路径
# 定义分库字段
spring.shardingsphere.sharding.default-database-strategy.standard.sharding-column=create_time
# 指定分库规则的 类的 路径
spring.shardingsphere.sharding.default-database-strategy.standard.precise-algorithm-class-name=com.util.PreciseModuloDatabaseShardingAlgorithm
spring.shardingsphere.sharding.tables.tab_user.actual-data-nodes=master0409$->{1..2}.tab_user$->{0..4}
# 定义分表字段
spring.shardingsphere.sharding.default-table-strategy.standard.sharding-column=create_time
# 指定分表规则的 类的 路径
spring.shardingsphere.sharding.default-table-strategy.standard.precise-algorithm-class-name=com.util.PreciseModuloTableShardingAlgorithm
https://blog.csdn.net/qq_34227896/article/details/102874568
https://blog.csdn.net/qq_34227896/article/details/102874568
https://blog.csdn.net/qq_34227896/article/details/102874568