Sharding-JDBC 5.4.1+SpringBoot3.4.1+MySQL8.4.1 使用案例

最近在升级 SpringBoot 项目,原版本是 2.7.16,要升级到 3.4.0 ,JDK 版本要从 JDK8 升级 JDK21,原项目中使用了 Sharding-JDBC,版本 4.0.0-RC1,在升级 SpringBoot 版本到 3.4.0 之后,服务启动失败,因此选择升级 Sharding-JDBC,记录代码如下:

环境

SpringBoot 3.4.1
Sharding-JDBC 5.4.1
MySQL 8.4.1

代码实现

下面通过代码实现,根据年份分表,2020 年之前数据一张表,之后每 2 年一张表。

准备测试数据 SQL

create table t_order
(id          int auto_incrementprimary key,order_id    varchar(36)                        null comment '订单ID',amount      decimal(18, 2)                     null comment '金额',order_year  int                                null comment '订单年份,用来作为分表字段',create_time datetime default CURRENT_TIMESTAMP null,update_time datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP,is_del      bit                                null
)comment '逻辑表,该表没有数据,但是没有这张表,sharding-jdbc执行时会报错';create table t_order_0
(id          int auto_incrementprimary key,order_id    varchar(36)                        null comment '订单ID',amount      decimal(18, 2)                     null comment '金额',order_year  int                                null comment '订单年份,用来作为分表字段',create_time datetime default CURRENT_TIMESTAMP null,update_time datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP,is_del      bit                                null
)comment '2020年以前的订单数据';create table t_order_2020
(id          int auto_incrementprimary key,order_id    varchar(36)                        null comment '订单ID',amount      decimal(18, 2)                     null comment '金额',order_year  int                                null comment '订单年份,用来作为分表字段',create_time datetime default CURRENT_TIMESTAMP null,update_time datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP,is_del      bit                                null
)comment '2020、2021年的订单数据';create table t_order_2022
(id          int auto_incrementprimary key,order_id    varchar(36)                        null comment '订单ID',amount      decimal(18, 2)                     null comment '金额',order_year  int                                null comment '订单年份,用来作为分表字段',create_time datetime default CURRENT_TIMESTAMP null,update_time datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP,is_del      bit                                null
)comment '2021、2022年的订单数据';create table t_order_2024
(id          int auto_incrementprimary key,order_id    varchar(36)                        null comment '订单ID',amount      decimal(18, 2)                     null comment '金额',order_year  int                                null comment '订单年份,用来作为分表字段',create_time datetime default CURRENT_TIMESTAMP null,update_time datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP,is_del      bit                                null
)comment '2023、2024年的订单数据';INSERT INTO db2025.t_order_2022 (order_id, amount, order_year) VALUES ('76cfe091-d87f-11ef-b84b-0242ac110002', 7777.13, 2022);
INSERT INTO db2025.t_order_2024 (order_id, amount, order_year) VALUES ('76d66bb8-d87f-11ef-b84b-0242ac110002', 3106.80, 2023);

搭建 SpringBoot 项目
pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.4.1</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.wheelmouse</groupId><artifactId>sharding-sphere-case</artifactId><version>0.0.1-SNAPSHOT</version><name>sharding-sphere-case</name><description>sharding-sphere-case</description><url/><licenses><license/></licenses><developers><developer/></developers><scm><connection/><developerConnection/><tag/><url/></scm><properties><java.version>21</java.version><shardingsphere.version>5.4.1</shardingsphere.version><mybatis-plus.version>3.5.9</mybatis-plus.version></properties><dependencies><dependency><groupId>org.apache.shardingsphere</groupId><artifactId>shardingsphere-jdbc-core</artifactId><version>${shardingsphere.version}</version><exclusions><exclusion><groupId>org.yaml</groupId><artifactId>snakeyaml</artifactId></exclusion></exclusions></dependency><!-- 版本冲突	--><dependency><groupId>org.yaml</groupId><artifactId>snakeyaml</artifactId><version>1.33</version></dependency><dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId><version>2.3.1</version> <!-- 根据你的Java版本选择合适的版本 --></dependency><dependency><groupId>org.glassfish.jaxb</groupId><artifactId>jaxb-runtime</artifactId><version>2.3.1</version> <!-- 根据你的Java版本选择合适的版本 --></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jdbc</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- MyBatis-Plus --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.7</version></dependency><!-- Mybatis的分页插件 --><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.3.0</version></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- MyBatis-Plus --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId><version>${mybatis-plus.version}</version></dependency><!-- 于 v3.5.9 起,PaginationInnerInterceptor 已分离出来。如需使用,则需单独引入 mybatis-plus-jsqlparser 依赖,jdk 11+ 引入可选模块 --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-jsqlparser</artifactId><version>${mybatis-plus.version}</version></dependency><!-- Mybatis的分页插件, --><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.3.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><annotationProcessorPaths><path><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></path></annotationProcessorPaths></configuration></plugin><plugin><groupId>org.graalvm.buildtools</groupId><artifactId>native-maven-plugin</artifactId></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>

Mapper

/**
* @author 重楼
* @description 针对表【t_order】的数据库操作Mapper
* @createDate 2025-01-23 12:55:01
* @Entity generator.domain.Order0
*/
public interface OrderMapper extends BaseMapper<Order> {}

Mapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wheelmouse.shardingsphere.mapper.OrderMapper"><resultMap id="BaseResultMap" type="com.wheelmouse.shardingsphere.domain.Order"><id property="id" column="id" jdbcType="INTEGER"/><result property="orderId" column="order_id" jdbcType="VARCHAR"/><result property="amount" column="amount" jdbcType="DECIMAL"/><result property="orderYear" column="order_year" jdbcType="INTEGER"/><result property="createTime" column="create_time" jdbcType="TIMESTAMP"/><result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/><result property="isDel" column="is_del" jdbcType="BIT"/></resultMap><sql id="Base_Column_List">id,order_id,amount,order_year,create_time,update_time,is_del</sql>
</mapper>

Service

/**
* @author 重楼
* @description 针对表【t_order】的数据库操作Service
* @createDate 2025-01-23 12:55:01
*/
public interface OrderService extends IService<Order> {}

ServiceImpl

/**
* @author 重楼
* @description 针对表【t_order】的数据库操作Service实现
* @createDate 2025-01-23 12:55:01
*/
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order>implements OrderService {}

以下是Sharding-jdbc的配置类,Sharding-jdbc支持yaml和java 2中方式配置,这里采用java方式配置
ShardingConfig

/*** @author 重楼* @date 2025/1/14* @apiNote*/
@Configuration
public class ShardingConfig {@Beanpublic DataSource dataSource() throws SQLException {// 配置数据源Map<String, DataSource> dataSourceMap = new HashMap<>();dataSourceMap.put("ds0", createDataSource("com.mysql.cj.jdbc.Driver","jdbc:mysql://localhost:3306/db2025?serverTimezone=UTC&useSSL=false", // MySQL URL"root", // 用户名"123456" // 密码));// 这里的案例是单库,所以没有做读个数据源配置//dataSourceMap.put("ds1", createDataSource("com.mysql.cj.jdbc.Driver",//        "jdbc:mysql://127.0.0.1:3306/db2025?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true", // MySQL URL//        "root", // 用户名//        "123456" // 密码//));// 配置 Sharding-JDBC 的分片规则ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();shardingRuleConfig.getTables().add(getOrderTableRuleConfiguration());// 注册自定义分片算法// algorithmName 由用户指定,需要和分片策略中的分片算法一致// type 和 props,请参考分片内置算法:https://shardingsphere.apache.org/document/current/cn/user-manual/common-config/builtin-algorithm/sharding/Properties shardingAlgorithmProps = new Properties();shardingAlgorithmProps.setProperty("strategy", "COMPLEX"); // 指定算法类型shardingAlgorithmProps.setProperty("algorithmClassName", MyComplexKeysShardingAlgorithm.class.getName());shardingRuleConfig.getShardingAlgorithms().put("my-complex-keys-sharding-algorithm",new AlgorithmConfiguration("CLASS_BASED", shardingAlgorithmProps));// 创建 ShardingSphere 数据源Properties properties = new Properties();properties.put("sql-show", true);return ShardingSphereDataSourceFactory.createDataSource(dataSourceMap,Collections.singleton(shardingRuleConfig), properties);}private ShardingTableRuleConfiguration getOrderTableRuleConfiguration() {// 配置表规则ShardingTableRuleConfiguration tableRuleConfig = new ShardingTableRuleConfiguration("t_order", // 逻辑表名"ds0.t_order_${[" + orderActualDataNodes() + "]}" // 实际数据节点);// 配置复合分片策略tableRuleConfig.setTableShardingStrategy(new ComplexShardingStrategyConfiguration("order_year", // 分片键"my-complex-keys-sharding-algorithm" // 自定义分片算法名称));return tableRuleConfig;}/*** 自己实现,这里演示所以写死表名* @return*/private String orderActualDataNodes(){return "0,2020,2022,2024";}private DataSource createDataSource(final String driverClassName,final String url, final String username, final String password) {HikariDataSource dataSource = new HikariDataSource();dataSource.setDriverClassName(driverClassName);dataSource.setJdbcUrl(url); // MySQL 连接 URLdataSource.setUsername(username); // 数据库用户名dataSource.setPassword(password); // 数据库密码dataSource.setMaximumPoolSize(10); // 连接池最大连接数dataSource.setMinimumIdle(2); // 连接池最小空闲连接数dataSource.setIdleTimeout(30000); // 空闲连接超时时间dataSource.setMaxLifetime(1800000); // 连接最大存活时间dataSource.setConnectionTimeout(30000); // 连接超时时间return dataSource;}}

自定义分片算法实现类

/*** @author 重楼* @date 2025/1/10* @apiNote*/
@Component
public class MyComplexKeysShardingAlgorithm implements ComplexKeysShardingAlgorithm<String> {private static final Logger LOGGER = LoggerFactory.getLogger(MyComplexKeysShardingAlgorithm.class);@Overridepublic Collection<String> doSharding(Collection<String> availableTargetNames, ComplexKeysShardingValue<String> shardingValue) {Map<String, Collection<String>> columnNameAndShardingValuesMap = shardingValue.getColumnNameAndShardingValuesMap();// 获取 列名-值-方式1,范围查询Map<String, Range<String>> columnNameAndRangeValuesMap = shardingValue.getColumnNameAndRangeValuesMap();boolean hasDateYear = columnNameAndRangeValuesMap.containsKey("order_year");if (!hasDateYear) {return Lists.newArrayList();}Range<String> orderYear = columnNameAndRangeValuesMap.get("order_year");String orderIdUpperValue = orderYear.upperEndpoint();// 上限String orderIdLowerValue = orderYear.lowerEndpoint();// 下限String tablePrefix = "t_order";// 根据年份拼接物理表表名List<String> actualTableList = Lists.newArrayList();for (int dateYear = Integer.parseInt(orderIdLowerValue); dateYear <= Integer.parseInt(orderIdUpperValue); dateYear++) {// 如果交易年份小于2020则使用t_order_0,如果交易时间大于当前年则忽略//按照不同时间类型分的表  两年一张,小于2020年以前的数据数据都放在_0结尾的表中if (dateYear < 2020) {actualTableList.add(tablePrefix  + "_0");continue;}if (dateYear > Year.now().getValue()) {continue;}// 计算年份落在哪个时间分片键上int yearSharding = dateYear - (dateYear % 2);actualTableList.add(tablePrefix + "_" + yearSharding);}actualTableList = actualTableList.stream().distinct().collect(Collectors.toList());LOGGER.info("actual table name is :{}", actualTableList);return actualTableList;}

通过SPI的方式注册该算法,在 resources 文件夹下创建文件夹 META-INF/services。 在该文件夹下创建文件 org.apache.shardingsphere.sharding.spi.ShardingAlgorithm, 文件内写上我们自定义的分片算法。

com.wheelmouse.shardingsphere.config.MyComplexKeysShardingAlgorithm

测试类

@SpringBootTest
class ShardingSphereCaseApplicationTests {private final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");@Autowiredprivate OrderMapper orderMapper;@Testvoid list() {QueryWrapper<Order> queryWrapper = new QueryWrapper<>();queryWrapper.between("order_year", "2022", "2024");List<Order> list = orderMapper.selectList(queryWrapper);for (Order order : list) {System.out.println(order);}}}

结果:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/6532.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Django】多个APP设置独立的URL

目录 方法一&#xff1a;各个App下设置自己的URL 1、在各自的App当中创建urls.py文件​编辑 2、在主urls当中包含子url 3、各App的urls中设置url 4、设置后台函数 5、最终结果 总结&#xff1a; 方法二&#xff1a;利用as方法&#xff0c;在总的URL中对views重命名 实…

Vue2 项目二次封装Axios

引言 在现代前端开发中&#xff0c;HTTP请求管理是构建健壮应用的核心能力之一。Axios作为目前最流行的HTTP客户端库&#xff0c;其灵活性和可扩展性为开发者提供了强大的基础能力。 1. 为什么要二次封装Axios&#xff1f; 1.1 统一项目管理需求 API路径标准化&#xff1a;…

【算法】经典博弈论问题——巴什博弈 python

目录 前言巴什博弈(Bash Game)小试牛刀PN分析实战检验总结 前言 博弈类问题大致分为&#xff1a; 公平组合游戏、非公平组合游戏&#xff08;绝大多数的棋类游戏&#xff09;和 反常游戏 巴什博弈(Bash Game) 一共有n颗石子&#xff0c;两个人轮流拿&#xff0c;每次可以拿1~m颗…

软件开发学习路线——roadmap

推荐软件学习路线网站&#xff1a;https://roadmap.sh/get-started 有有关前端后端开发的学习路径&#xff0c;也有AI&#xff0c;移动开发&#xff0c;管理相关的学习路径 会有相应的词条路径&#xff0c;深入学习 右上角可以设置学习任务的完成情况

Moretl FileSync增量文件采集工具

永久免费: <下载> <使用说明> 我们希望Moretl FileSync是一款通用性很好的文件日志采集工具,解决工厂环境下,通过共享目录采集文件,SMB协议存在的安全性,兼容性的问题. 同时,我们发现工厂设备日志一般为增量,为方便MES,QMS等后端系统直接使用数据,我们推出了增量采…

9、Docker环境安装Nginx

一、拉取镜像 docker pull nginx:1.24.0二、创建映射目录 作用&#xff1a;是将docker中nginx的相关配置信息映射到外面&#xff0c;方便修改配置文件 1、创建目录 # cd home/ # mkdir nginx/ # cd nginx/ # mkdir conf html log2、生成容器 docker run -p 80:80 -d --name…

023:到底什么是感受野?

本文为合集收录&#xff0c;欢迎查看合集/专栏链接进行全部合集的系统学习。 合集完整版请查看这里。 在前面介绍卷积算法时&#xff0c;一直在强调一个内容&#xff0c;那就是卷积算法的运算过程是—— 卷积核在输入图像上滑动扫描的过程。 在每一次扫描时&#xff0c;可以…

BGP(1)邻居建立,路由宣告

拓扑如图&#xff0c;配置地址&#xff0c;配置ospf并宣告相应地址 1、观察bgp邻居的建立 a R1和R3建立bgp邻居 抓包可以看到TCP的三次握手&#xff0c;端口号179 可以看到R1和R3成功建立了IBGP邻居 b 缺省情况下&#xff0c;BGP使用报文出接口作为TCP连接的本地接口&#x…

Python 预训练:打通视觉与大语言模型应用壁垒——Python预训练视觉和大语言模型

大语言模型是一种由包含数百亿甚至更多参数的深度神经网络构建的语言模型&#xff0c;通常使用自监督学习方法通过大量无标签文本进行训练&#xff0c;是深度学习之后的又一大人工智能技术革命。 大语言模型的发展主要经历了基础模型阶段(2018 年到2021年)、能力探索阶段(2019年…

【数据库】详解MySQL数据库中的事务与锁

目录 1.数据库事务 1.1.事务的四大特性 1.2.事务开启的方式 1.3.读一致性问题及其解决 2.MVCC解决读一致性问题原理 2.1.MVCC概念 2.2.准备环境 3.MySQL中的锁 3.1.行锁之共享锁 3.2.行锁之排它锁 1.数据库事务 数据库事务&#xff08;Transaction&#xff09;是一种…

C语言文件操作

本文重点&#xff1a; 什么是文件 文件名 文件类型 文件缓冲区 文件指针 文件的打开和关闭 文件的顺序读写 文件的随机读写 文件结束的判定 什么是文件 磁盘上的文件是文件。 但是在程序设计中&#xff0c;我们一般谈的文件有两种&#xff1a;程序文件、数…

Ubuntu24.04初始化MySQL报错 error while loading shared libraries libaio.so.1

Ubuntu24.04初始化MySQL报错 error while loading shared libraries: libaio.so.1 问题一&#xff1a;libaio1不存在 # 提示libaio1不存在 [rootzabbix-mysql-master.example.com x86_64-linux-gnu]#apt install numactl libaio1 Reading package lists... Done Building depe…

『 实战项目 』Cloud Backup System - 云备份

文章目录 云备份项目服务端功能服务端功能模块划分客户端功能客户端模块划分 项目条件Jsoncpp第三方库Bundle第三方库httplib第三方库Request类Response类Server类Client类搭建简单服务器搭建简单客户端 服务端工具类实现 - 文件实用工具类服务器配置信息模块实现- 系统配置信息…

No.36 学习 | Python 函数:从基础到实战

最近我在学 Python 编程&#xff0c;今天可算是狠狠钻研了一把 Python 里的函数&#xff0c;感觉脑袋里的知识又充实了不少&#xff0c;赶紧来记一记。 一、Python函数基础概念 &#xff08;一&#xff09;pass语句&#xff1a;代码块的“占位符” 在编写代码时&#xff0c;有…

easyexcel读取写入excel easyexceldemo

1.新建springboot项目 2.添加pom依赖 <name>excel</name> <description>excelspringboot例子</description><parent> <groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId&…

Qt 5.14.2 学习记录 —— 십유 布局管理器

文章目录 1、QVBoxLayout2、QHBoxLayout3、QGridLayout4、QFormLayout5、QSpacerItem 布局管理器是为了让程序员不需要自己决定控件的绝对位置&#xff0c;而是通过布局管理器方便地放置 1、QVBoxLayout 垂直布局管理器 #include <QPushButton> #include <QVBoxLayo…

Markdown Viewer 浏览器, vscode

使用VS Code插件打造完美的MarkDown编辑器&#xff08;插件安装、插件配置、markdown语法&#xff09;_vscode markdown-CSDN博客 右键 .md 文件&#xff0c;选择打开 方式 &#xff08;安装一些markdown的插件) vscode如何预览markdown文件 | Fromidea GitCode - 全球开发者…

每日十题八股-2025年1月23日

1.快排为什么时间复杂度最差是O&#xff08;n^2&#xff09; 2.快排这么强&#xff0c;那冒泡排序还有必要吗&#xff1f; 3.如果要对一个很大的数据集&#xff0c;进行排序&#xff0c;而没办法一次性在内存排序&#xff0c;这时候怎么办&#xff1f; 4.面试官&#xff1a;你的…

H3C-无线WLAN配置案例(二层隧道转发)

目录 1.无线wlan产生背景:2.网络拓扑:3.网络简述:4.网络配置:4.1 网络基础配置4.2 无线wlan二层隧道转发配置4.3 无线wlan验证: 1.无线wlan产生背景: 无线WLAN&#xff08;无线局域网&#xff09;的产生背景主要源于以下几个方面的需求和技术发展&#xff1a;移动性和便捷性需…

HarmonyOS Next构建工具 lycium 原理介绍

HarmonyOS Next构建工具 lycium 原理介绍 背景介绍 HarmonyOS Next中很多系统API是以C接口提供&#xff0c;如果要使用C接口&#xff0c;必须要使用NAPI在ArkTS与C间交互&#xff0c;这种场景在使用DevEco-Studio中集成的交叉编译工具&#xff0c;以及cmake构建工具就完全够用…