SpringBoot集成Sharding-JDBC实现分库分表方式

 更新时间:2024年07月13日 08:58:19   作者:DanceDonkey  
这篇文章主要介绍了SpringBoot集成Sharding-JDBC实现分库分表方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

一、环境搭建

1.创建一个springboot项目,引入以下依赖。

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
		</dependency>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid-spring-boot-starter</artifactId>
			<version>1.1.20</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>
		<dependency>
			<groupId>org.apache.shardingsphere</groupId>
			<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
			<version>4.0.0-RC1</version>
		</dependency>
		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-boot-starter</artifactId>
			<version>3.0.5</version>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
		</dependency>
	</dependencies>

2.创建一个数据库user和两张表user_1,user_2

CREATE DATABASE `user`;

CREATE TABLE `user_1` (
  `id` bigint(30) NOT NULL,
  `username` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  `gender` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8


CREATE TABLE `user_2` (
  `id` bigint(30) NOT NULL,
  `username` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  `gender` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

3.分别创建user表对应的实体类和mapper

实体类代码

@Data
public class User {

    private Long id;

    private String username;

    private String password;
    
    private String gender;

}

mapper代码

public interface UserMapper extends BaseMapper<User>{

}

结构图:

二、实现水平分表

需求:现在有两个user表,一个是user_1,一个是user_2,当id为偶数的时候向user_1表中插入数据,当id为奇数的时候向user_2表中插入数据,实现水平分表。

1.配置application.properties

#指定当前应用的所有数据源标识(由于后期可能会涉及到多个数据源,或读写分离等,这里要为每个数据源
# 起一个标识名,然后为每个数据源具体配置)
spring.shardingsphere.datasource.names=d1
#配置d1这个数据源,由于这里是水平分表,所以只需要一个数据源即可 其中d1代表该数据源的一个标识
spring.shardingsphere.datasource.d1.type=com.alibaba.druid.pool.DruidDataSource
#指定链接驱动
spring.shardingsphere.datasource.d1.driver-class-name=com.mysql.cj.jdbc.Driver
#指定链接url
spring.shardingsphere.datasource.d1.url=jdbc:mysql://localhost:3308/user?useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
#指定链接用户名
spring.shardingsphere.datasource.d1.username=root
#指定链接密码
spring.shardingsphere.datasource.d1.password=root

#由于是水平分表,所以会涉及到多张相同的表,这里指定这些表的分布情况:在哪个数据源上,以及一共有几张表
#指定在d1数据源,且有user_1和user_2两张表
#$->{1..2}该表达式是与前面的user_相拼接的,不能乱写,例如我们现在的两张表名是user_1和user_2,那这里就是user_$->{1..2}
#如果我们分布了3张表 user_5,user_6,user_7,那这里就是user_$->{5..6..7}
spring.shardingsphere.sharding.tables.user.actual-data-nodes=d1.user_$->{1..2}

# 指定 user 表里面主键id 以及id的生成策略 SNOWFLAKE:表示用雪花算法生成该id
spring.shardingsphere.sharding.tables.user.key-generator.column=id
spring.shardingsphere.sharding.tables.user.key-generator.type=SNOWFLAKE

# 指定分片策略 约定 id 值偶数添加到 user_1 表,如果 id 是奇数添加到 user_2表
#指定要根据哪个字段进行分表,这里根据id进行分表
spring.shardingsphere.sharding.tables.user.table-strategy.inline.sharding-column=id
#执行分表的规则:注意这里是$->{id% 2 + 1},由于偶数%2的结果为0,但是我们并没有user_0这样表
#所以我们要在取模的结果上+1 这样就实现了如果是偶数那么取模的结果就是user_1,如果是奇数就是user_2
spring.shardingsphere.sharding.tables.user.table-strategy.inline.algorithm-expression=user_$->{id% 2 + 1}

#开启sql 输出日志
spring.shardingsphere.props.sql.show=true
# 由于一个实体类对应两张表,所以会产生覆盖操作,加上这个配置解决覆盖问题
spring.main.allow-bean-definition-overriding=true

2.编写测试代码

	@Test
	void testAddUser()   {
		for (int i = 0;i < 6;i++){
			User user = new User();
			user.setGender("0");
			user.setPassword(UUID.randomUUID().toString().substring(0,5));
			user.setUsername("-->" + i);
			userMapper.insert(user);
		}
	}

3.日志查看:

可以看到当user_id的值为偶数的时候,是向user_1表中插入的。

再看当user_id的值为奇数的时候,该条数据插入了user_2这个表。

三、实现水平分库

需求:现在有两个user库,一个是user_db1,一个是user_db2,每个user库中都有两张相同的表,user_1,user_2,当user对象的gender属性值为1的时候向user_db1库中插入,当user对象的gender属性值为0的时候向user_db2库中插入,这是分库的规则,分表的规则是,当id为偶数的时候向user_1表中插入数据,当id为奇数的时候向user_2表中插入数据。(建表语句和上面是相同的)

结构如下:

2.配置application.properties

#指定当前应用的所有数据源标识(由于后期可能会涉及到多个数据源,或读写分离等,这里要为每个数据源
# 起一个标识名,然后为每个数据源具体配置)
spring.shardingsphere.datasource.names=d1,d2
#配置d1这个数据源,由于这里是水平分表,所以只需要一个数据源即可 其中d1代表该数据源的一个标识
spring.shardingsphere.datasource.d1.type=com.alibaba.druid.pool.DruidDataSource
#指定链接驱动
spring.shardingsphere.datasource.d1.driver-class-name=com.mysql.cj.jdbc.Driver
#指定链接url
spring.shardingsphere.datasource.d1.url=jdbc:mysql://localhost:3308/user_db1?useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
#指定链接用户名
spring.shardingsphere.datasource.d1.username=root
#指定链接密码
spring.shardingsphere.datasource.d1.password=root

#由于是两个数据库,所以要配置两个数据源
#配置d2数据源
spring.shardingsphere.datasource.d2.type=com.alibaba.druid.pool.DruidDataSource
#指定链接驱动
spring.shardingsphere.datasource.d2.driver-class-name=com.mysql.cj.jdbc.Driver
#指定链接url
spring.shardingsphere.datasource.d2.url=jdbc:mysql://localhost:3308/user_db2?useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
#指定链接用户名
spring.shardingsphere.datasource.d2.username=root
#指定链接密码
spring.shardingsphere.datasource.d2.password=root


#指定数据库和表的分布情况
#指定数据库分布情况,数据库里面表分布情况
#d$->{1..2}.user_$->{1..2} 表示在d1,d2数据源上都有user_1和user_2两张表
spring.shardingsphere.sharding.tables.user.actual-data-nodes=d$->{1..2}.user_$->{1..2}

# 指定 user 表里面主键id 以及id的生成策略 SNOWFLAKE:表示用雪花算法生成该id
spring.shardingsphere.sharding.tables.user.key-generator.column=id
spring.shardingsphere.sharding.tables.user.key-generator.type=SNOWFLAKE

# 指定分片策略 约定 id 值偶数添加到 user_1 表,如果 id 是奇数添加到 user_2表
#指定要根据哪个字段进行分表,这里根据id进行分表
spring.shardingsphere.sharding.tables.user.table-strategy.inline.sharding-column=id
#执行分表的规则:注意这里是$->{id% 2 + 1},由于偶数%2的结果为0,但是我们并没有user_0这样表
#所以我们要在取模的结果上+1 这样就实现了如果是偶数那么取模的结果就是user_1,如果是奇数就是user_2
spring.shardingsphere.sharding.tables.user.table-strategy.inline.algorithm-expression=user_$->{id% 2 + 1}

#============================================================================================
#以上指定了分表策略,下面指定分库策略,也就是gender为0则向user_db1中插入,为1则向user_db2中插入
spring.shardingsphere.sharding.tables.user.database-strategy.inline..sharding-column=gender
#如果gender为0 则表达式{gender=='0'?1:2}的结果就是1,则d$->{gender=='0'?1:2} = d1,就会向d1数据源也就是user_db1库中添加
#如果gender为1 则表达式{gender=='0'?1:2}的结果就是2,则d$->{gender=='0'?1:2} = d2,就会向d1数据源也就是user_db2库中添加
spring.shardingsphere.sharding.tables.user.database-strategy.inline.algorithm-expression=d$->{gender=='0'?1:2}




#开启sql 输出日志
spring.shardingsphere.props.sql.show=true
# 由于一个实体类对应两张表,所以会产生覆盖操作,加上这个配置解决覆盖问题
spring.main.allow-bean-definition-overriding=true

2.编写测试代码

	@Test
	void testAddUser()   {
		for (int i = 0;i < 10;i++){
			User user = new User();
			user.setPassword(UUID.randomUUID().toString().substring(0,5));
			user.setUsername("-->" + i);
			if (i % 2 == 0) user.setGender("0");
			else user.setGender("1");
			userMapper.insert(user);
		}
	}

3.数据库查看

可以看到:gender为0,且id为偶数插入到了user_db1库中的,user_1表。

可以看到:gender为0,且id为奇数插入到了user_db1库中的,user_2表。

可以看到:gender为1,且id为偶数插入到了user_db2库中的,user_1表。

可以看到:gender为1,且id为奇数插入到了user_db2库中的,user_2表。

四、公共表的配置

有些表的数据量不大,需要在每个数据库中都有,这时需要配置公共表。

向user_db1,和user_db2两个数据库都创建一个t_dict表

CREATE table t_dicit(
	id BIGINT(30) PRIMARY key,
	`dstatus` VARCHAR(255) not null,
	`description` VARCHAR(255) not null
)

status和desc是mysql的两个关键字,表的字段名尽量避开这些关键字,否则会发生运行时异常。

1.配置application.properties

#指定当前应用的所有数据源标识(由于后期可能会涉及到多个数据源,或读写分离等,这里要为每个数据源
# 起一个标识名,然后为每个数据源具体配置)
spring.shardingsphere.datasource.names=d1,d2
#配置d1这个数据源,由于这里是水平分表,所以只需要一个数据源即可 其中d1代表该数据源的一个标识
spring.shardingsphere.datasource.d1.type=com.alibaba.druid.pool.DruidDataSource
#指定链接驱动
spring.shardingsphere.datasource.d1.driver-class-name=com.mysql.cj.jdbc.Driver
#指定链接url
spring.shardingsphere.datasource.d1.url=jdbc:mysql://localhost:3308/user_db1?useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
#指定链接用户名
spring.shardingsphere.datasource.d1.username=root
#指定链接密码
spring.shardingsphere.datasource.d1.password=root

#由于是两个数据库,所以要配置两个数据源
#配置d2数据源
spring.shardingsphere.datasource.d2.type=com.alibaba.druid.pool.DruidDataSource
#指定链接驱动
spring.shardingsphere.datasource.d2.driver-class-name=com.mysql.cj.jdbc.Driver
#指定链接url
spring.shardingsphere.datasource.d2.url=jdbc:mysql://localhost:3308/user_db2?useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
#指定链接用户名
spring.shardingsphere.datasource.d2.username=root
#指定链接密码
spring.shardingsphere.datasource.d2.password=root


#指定数据库和表的分布情况
#指定数据库分布情况,数据库里面表分布情况
#d$->{1..2}.user_$->{1..2} 表示在d1,d2数据源上都有user_1和user_2两张表
spring.shardingsphere.sharding.tables.user.actual-data-nodes=d$->{1..2}.user_$->{1..2}

# 指定 user 表里面主键id 以及id的生成策略 SNOWFLAKE:表示用雪花算法生成该id
spring.shardingsphere.sharding.tables.user.key-generator.column=id
spring.shardingsphere.sharding.tables.user.key-generator.type=SNOWFLAKE

# 指定分片策略 约定 id 值偶数添加到 user_1 表,如果 id 是奇数添加到 user_2表
#指定要根据哪个字段进行分表,这里根据id进行分表
spring.shardingsphere.sharding.tables.user.table-strategy.inline.sharding-column=id
#执行分表的规则:注意这里是$->{id% 2 + 1},由于偶数%2的结果为0,但是我们并没有user_0这样表
#所以我们要在取模的结果上+1 这样就实现了如果是偶数那么取模的结果就是user_1,如果是奇数就是user_2
spring.shardingsphere.sharding.tables.user.table-strategy.inline.algorithm-expression=user_$->{id% 2 + 1}

#============================================================================================
#以上指定了分表策略,下面指定分库策略,也就是gender为0则向user_db1中插入,为1则向user_db2中插入
spring.shardingsphere.sharding.tables.user.database-strategy.inline..sharding-column=gender
#如果gender为0 则表达式{gender=='0'?1:2}的结果就是1,则d$->{gender=='0'?1:2} = d1,就会向d1数据源也就是user_db1库中添加
#如果gender为1 则表达式{gender=='0'?1:2}的结果就是2,则d$->{gender=='0'?1:2} = d2,就会向d1数据源也就是user_db2库中添加
spring.shardingsphere.sharding.tables.user.database-strategy.inline.algorithm-expression=d$->{gender=='0'?1:2}


#============================================================================================
#配置公共表 在向t_dicit表插入数据时 这些默认的数据源(d1,d2)的t_dicit表都会插入该数据
spring.shardingsphere.sharding.broadcast-tables=t_dicit
spring.shardingsphere.sharding.tables.t_dicit.key-generator.column=id
spring.shardingsphere.sharding.tables.t_dicit.key-generator.type=SNOWFLAKE

#开启sql 输出日志
spring.shardingsphere.props.sql.show=true
# 由于一个实体类对应两张表,所以会产生覆盖操作,加上这个配置解决覆盖问题
spring.main.allow-bean-definition-overriding=true

2.编写实体类和mapper

@TableName("t_dicit")
@Data
public class Dict {

    @TableId
    private Long id;

    private String dstatus;

    private String description;

}
public interface DictMapper extends BaseMapper<Dict> {

}

3.编写测试程序

	@Test
	public void testDict(){
		Dict dict = new Dict();
		dict.setDescription("启用状态");
		dict.setDstatus("A");
		dictMapper.insert(dict);
	}

4.查看日志发现分别向两个数据源发送了sql

5.查看表

两个库的t_dicit表都有了该数据。

同样如果是删除公共表的数据也是同时将两个数据库中的记录删除。

	@Test
	public void testDictDel(){
		dictMapper.deleteById(1270356973266165762L);
	}

运行日志:

两个库中的数据都被删除。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 详解基于JWT的springboot权限验证技术实现

    详解基于JWT的springboot权限验证技术实现

    这篇文章主要介绍了详解基于JWT的springboot权限验证技术实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • java代码实现空间切割

    java代码实现空间切割

    大家好,本篇文章主要讲的是java代码实现空间切割,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-01-01
  • 我对@RestController注解的理解

    我对@RestController注解的理解

    这篇文章主要介绍了我对@RestController注解的理解,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • Java final关键字用法、场景、面试题全解析

    Java final关键字用法、场景、面试题全解析

    本文全程围绕final的核心用法展开,从“修饰变量、修饰方法、修饰类”三个核心场景,搭配实战代码、避坑细节,再补充高频面试题,帮你彻底吃透final,既适合新手入门,也适合巩固基础、备战面试,感兴趣的朋友一起看看吧
    2026-04-04
  • IDEA插件EasyCode及MyBatis最优配置步骤详解

    IDEA插件EasyCode及MyBatis最优配置步骤详解

    这篇文章主要介绍了IDEA插件EasyCode MyBatis最优配置步骤详解,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-12-12
  • java String、StringBuilder和StringBuffer的区别详解

    java String、StringBuilder和StringBuffer的区别详解

    这篇文章主要介绍了java String、StringBuilder和StringBuffer的区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-01-01
  • spring boot 集成 swagger3及配置方法

    spring boot 集成 swagger3及配置方法

    Swagger 3是一种开源的API描述工具,它可以帮助开发人员设计、构建、文档化和测试API,这篇文章主要介绍了spring boot 集成 swagger3,需要的朋友可以参考下
    2023-05-05
  • Java中反射reflect的基础知识讲解

    Java中反射reflect的基础知识讲解

    这篇文章主要介绍了Java中反射reflect的基础知识讲解,Java中的反射,它算是Java当中非常底层的一个技术,平时我们我们用得不多,实际上它也的确非常复杂同时也难以理解,但是涉及到底层的东西Java都给我们封装好了,我们直接拿来调用即可,需要的朋友可以参考下
    2023-10-10
  • 一文带你深入剖析Java线程池的前世今生

    一文带你深入剖析Java线程池的前世今生

    这篇文章主要带大家介绍了深入剖析一下Java线程池的前世今生,了解线程池的原理以及为什么需要线程池。文中的示例代码讲解详细,需要的可以参考一下
    2022-10-10
  • SpringBoot处理HTTP请求的详细流程

    SpringBoot处理HTTP请求的详细流程

    这篇文章主要介绍了SpringBoot处理HTTP请求的详细流程,文中通过代码示例给大家介绍的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-05-05

最新评论