看完这篇,别再说不会Spring 分库分表了

多数据源,读写分离,分库分表,基本上已经是现在任何一个项目的基本配置了,在之前的文章
Spring多数据源实现icon-default.png?t=N6B9https://blog.csdn.net/wangerrong/article/details/131910740  里讲了多数据源的实现,其实已经包含了读写分离(master和slave分别配置主库和只读库就好了),现在就记录下分库分表的实现过程。

1,引入jdbc, mybatis, shardingsphere等依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId><version>2.4.2</version>
</dependency>
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.30</version>
</dependency>
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>8.0.30</version>
</dependency>
<!-- jpa持久化工具 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId><version>2.7.6</version>
</dependency>
<!-- 必须引入的包 ShardingSphere -->
<dependency><groupId>org.apache.shardingsphere</groupId><artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId><version>5.2.0</version>
</dependency>

2,建立数据库和数据表

 

3,添加分库分表配置到bootsrap.yml

server:port: 9102
# NaCos
spring:application:name: deviceserviceshardingsphere:# 数据源配置datasource:# 数据源名称,多数据源以逗号分隔names: db0,db1db0:type: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverjdbc-url: jdbc:mysql://xxxx:3306/db_0?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=trueusername: rootpassword: xxxxxxxxxdb1:type: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverjdbc-url: jdbc:mysql://yyyy:3306/db_1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=trueusername: rootpassword: yyyyyyyyy# 分片规则配置rules:sharding:# 分片算法配置sharding-algorithms:database-inline:# 分片算法类型type: INLINEprops:# 分片算法的行表达式(算法自行定义,此处为方便演示效果)algorithm-expression: db$->{order_id%10 > 4?1:0}# 关键,查询时是否在所有分库分表中查询allow-range-query-with-inline-sharding: truetable-inline:# 分片算法类型type: INLINEprops:# 分片算法的行表达式algorithm-expression: t_order_$->{order_id % 3}# 关键,查询时是否在所有分库分表中查询allow-range-query-with-inline-sharding: truetables:# 逻辑表名称t_order:# 行表达式标识符可以使用 ${...} 或 $->{...},但前者与 Spring 本身的属性文件占位符冲突,因此在 Spring 环境中使用行表达式标识符建议使用 $->{...}actual-data-nodes: db${0..1}.t_order_${0..2}# 分库策略database-strategy:standard:# 分片列名称sharding-column: order_id# 分片算法名称sharding-algorithm-name: database-inline# 分表策略table-strategy:standard:# 分片列名称sharding-column: order_id# 分片算法名称sharding-algorithm-name: table-inline# 属性配置props:# 展示修改以后的sql语句sql-show: trueprofiles:active: dev
---
spring:config:activate:on-profile: devimport: optional:config\application-dev.yml

4,  实体类和mapper

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;@Data
@TableName("t_order")
public class Order {private long orderId;private String createdTime;
}
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;@Data
@TableName("t_device")
public class Device {private long deviceId;private String name;private String createdTime;
}

 

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xxx.domain.Order;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;@Mapper
@Repository
public interface OrderMapper extends BaseMapper<Order> {}
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xxx.domain.Device;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;@Mapper
@Repository
public interface DeviceMapper extends BaseMapper<Device> {
}

 


import com.xxx.domain.Order;
import org.springframework.stereotype.Service;import java.util.List;@Service
public interface OrderService {public void saveOrder(Order order);public List<Order> list();public void delete(long orderId);public void update(long orderId);
}
import com.xxx.domain.Device;
import org.springframework.stereotype.Service;@Service
public interface DeviceService {public void saveDevice(Device device);
}

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xxx.domain.Order;
import com.xxx.mapper.OrderMapper;
import com.xxx.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;@Service
public class OrderServiceImpl implements OrderService {@Autowiredprivate OrderMapper orderMapper;@Overridepublic void saveOrder(Order order) {orderMapper.insert(order);}@Overridepublic void delete(long orderId) {QueryWrapper qw = new QueryWrapper<Order>();qw.eq("order_id",orderId);orderMapper.delete(qw);}@Overridepublic void update(long orderId) {Order order = new Order();order.setOrderId(orderId);order.setCreatedTime("2200-07-26 00:00:01");QueryWrapper qw = new QueryWrapper<Order>();qw.eq("order_id",orderId);orderMapper.update(order,qw);}@Overridepublic List<Order> list() {QueryWrapper qw = new QueryWrapper<Order>();qw.ge("order_id",0);qw.orderByAsc("order_id");return orderMapper.selectList(qw);}
}
import com.xxx.domain.Device;
import com.xxx.mapper.DeviceMapper;
import com.xxx.service.DeviceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class DeviceServiceImpl implements DeviceService {@Autowiredprivate DeviceMapper deviceMapper;@Overridepublic void saveDevice(Device device) {deviceMapper.insert(device);}
}

import com.xxx.common.UserContext;
import com.xxx.domain.Device;
import com.xxx.domain.Order;
import com.xxx.service.DeviceService;
import com.xxx.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;@RestController
@RefreshScope
@Slf4j
@RequestMapping("/device")
public class DeviceController extends AbstractController{@Autowiredprivate OrderService orderService;@Autowiredprivate DeviceService devieService;@GetMapping("/save")public String save(@RequestParam("orderId") int orderId){Order order = new Order();order.setOrderId(orderId);DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");String dateStr = sdf.format(new Date());order.setCreatedTime(dateStr);orderService.saveOrder(order);Device device = new Device();device.setDeviceId(orderId);device.setName(orderId+"_"+dateStr);device.setCreatedTime(dateStr);devieService.saveDevice(device);return "success";}@GetMapping("/delete")public String delete(@RequestParam("orderId") long orderId) {orderService.delete(orderId);return "success";}@GetMapping("/update")public String update(@RequestParam("orderId") int orderId) {orderService.update(orderId);return "success";}@GetMapping("/list")public List<Order> list() {return orderService.list();}
}

上面代码是一个简单的验证:

1,  通过对做了分库分表配置的t_order表的增删改查,验证分库分表后的增删改查是否生效,验证通过

2,验证对没做分库分表配置的t_device表的增加,验证正常数据库操作(默认走spring.shardingsphere.datasource.names: db0,db1配置里的第一个数据库)是否生效,验证通过

5,总结

Springboot + shardingsphere 实现分库分表的需求,比较简单,但是要想真正地投入实用,还有很多路要走,比如实现自定义分库分表规则的算法,自定义分布式表的主键ID,基于分库分表后的排序(默认已实现按分库分表的列进行排序)和分页等等等。

码字不易,记得点赞关注哟!

 

 

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

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

相关文章

Linux使用教程

一、Linux命令基础 1、ls、ll命令——展示数据 ①ls命令——平铺展示数据 其中ls命令以平铺的方式展现数据 ②ll命令——列表展示数据 ll命令以列表的方式展现数据 -a选项&#xff0c;表示&#xff1a;all的意思&#xff0c;即列出全部文件&#xff08;包含隐藏的文件/文件夹…

ARM寄存器组织

一、寄存器二、ARM寄存器三、专用寄存器四、CPSR寄存器 一、寄存器 概念 寄存器是处理器内部的存储器&#xff0c;没有地址 作用 一般用于暂时存放参与运算的数据和运算结果 分类 包括通用寄存器、专用寄存器、控制寄存器 二、ARM寄存器 注 在某个特定模式下只能使用当前模…

Solidity合约开发注意项

目录 一、原则二、查询里的异常处理三、小数四、访问子合约的变量五、实现结构体继承的功能六、address转string七、字符串判等比较八、简单的地址合法性校验九、字符串拼接十、实现Set集合十一、参数是结构体的event的签名 最近在开发一组自主链权限治理的Solidity合约&#x…

Web浪漫历程:揭秘二十年间与您“约会”的浏览器发展

&#x1f9d1;‍&#x1f4bc; 个人简介&#xff1a;一个不甘平庸的平凡人&#x1f36c; &#x1f5a5;️ Node专栏&#xff1a;Node.js从入门到精通 &#x1f5a5;️ TS知识总结&#xff1a;十万字TS知识点总结 &#x1f449; 你的一键三连是我更新的最大动力❤️&#xff01;…

Kafka基础架构与核心概念

Kafka简介 Kafka是由Apache软件基金会开发的一个开源流处理平台&#xff0c;由Scala和Java编写。Kafka是一种高吞吐量的分布式发布订阅消息系统&#xff0c;它可以处理消费者在网站中的所有动作流数据。架构特点是分区、多副本、多生产者、多订阅者&#xff0c;性能特点主要是…

React + 二级目录 + Nginx配置

背景&#xff1a; 由于子域名有限&#xff0c;我们需要将不同的前端项目进行二级目录区分。 一、项目 现有三个项目&#xff1a; bsrm-web-manage bsrm-web-operator bsrm-web-testingorganization 二、期望访问路径 http://bsrm.life.com/bsrm-web-manage http://bsrm.lif…

手机照片误删除?无需担忧,点击这里,即可轻松恢复

手机照片误删除&#xff1f;无需担忧&#xff0c;点击这里&#xff0c;即可轻松恢复 开头&#xff1a;在数字化时代&#xff0c;手机已成为我们生活中不可或缺的伙伴。随着手机摄影的普及&#xff0c;我们记录了许多珍贵的瞬间和回忆。然而&#xff0c;有时候我们不小心误删除…

Python编译过程和执行原理

hello&#xff0c;这里是Token_w的文章&#xff0c;主要讲解python的基础学习&#xff0c;希望对大家有所帮助 整理不易&#xff0c;感觉还不错的可以点赞收藏评论支持&#xff0c;感谢&#xff01; 目录 一. Python执行原理二. Python内部执行过程2.1 编译过程概述2.2 过程图解…

遥感数字图像处理实验教程(韦玉春)--部分实验问题回答

个人的学习思考&#xff0c;仅供参考。 目录 实验三、图像合成和显示增强 一、目的 二、要求 三、实验 实验五、图像变换 一、目的 二、要求 三、实验 实验六、图像滤波 一、目的 二、要求 三、实验 实验七、图像分割 一、目的 二、要求 三、实验 实验八、图…

linux判断端口是否占用(好用)

netstat 一般的话使用 netstat -tunlp | grep xxx参数作用-t指明显示TCP端口-u指明显示UDP端口-l仅显示监听套接字(所谓套接字就是使应用程序能够读写与收发通讯协议(protocol)与资料的程序)-p显示进程标识符和程序名称&#xff0c;每一个套接字/端口都属于一个程序。-n不进行…

Could not find toolchain file: E:/Git/build/cmake/android.toolchain.cmake问题解决

问题描述 在Windows下编译MNN的Android平台时&#xff0c;需要运行.sh文件&#xff0c;那么之后几种方式&#xff1a; 在power shell中启动git bash&#xff0c;但是这个窗口一闪而过&#xff0c;看不清输出的信息&#xff0c;可以通过在脚本中最后一行加入&#xff1a;sleep…

如何轻松找到竞品独立站?竞品独立站搜罗神器曝光!

独立站竞品调研对做好独立站来说的重要性不言而喻。还在纠结想做独立站但不会找竞品独立站&#xff1f;不知道怎么分析竞品独立站&#xff1f;今天东哥倾囊相授&#xff0c;把压箱底的秘籍教给你&#xff01; 怎么找竞品独立站&#xff1f; 1、谷歌购物广告 在谷歌购物页搜索产…

爬虫002_python程序的终端运行_文件运行_ipython的使用---python工作笔记020

用python运行一个文件,就是要写一个.py结尾的文件 然后保存 然后直接cmd中,python 然后写上py文件的路径就可以了 然后看一下内容 看一下终端中运行,直接输入python进入python环境,然后写python代码 回车运行 退出可以用exit()

设计模式——单例模式

1 概述 单例模式就是保证一个类只有一个对象实例。 为了保证无法创建多余的对象实例&#xff0c;单例类中需要自己创建对象实例&#xff0c;并把自己的构造方法私有化以防止其他地方调用创建对象&#xff0c;且需要提供一个公共的方法给其他类来获取该单例类的实例。 同时单例…

Linux笔记——rpm与yum下载软件命令介绍

系列文章目录 Linux笔记——进程管理Linux笔记——进程管理与网络监控技术讲解Linux笔记——进程管理 Linux笔记——管道相关命令以及shell编程 Linux笔记——磁盘进行分区与挂载介绍 文章目录 系列文章目录 前言 一 RPM介绍 1.1 RPM简单介绍 1.2 RPM命令语法 1.2.1 …

数学建模学习(2):数学建模各类常用的算法全解析

一、评价类算法 常见的评价算法 1.层次分析法 基本思想 是定性与定量相结合的多准则决策、评价方法。将决策的有关元素分解成 目标层、准则层和方案层 &#xff0c;并通过人们的 判断对决策方案的 优劣进行排序 &#xff0c;在此基础上进行定性和定量分析。它把人的思维过程…

工程师副高职称的评审条件

根据《专业技术人员职务评审暂行规定》和《工程技术人员职务评审暂行办法》&#xff0c;工程师副高职称的评审条件主要包括以下几方面&#xff1a; • 学历要求&#xff1a;具有本科及以上学历&#xff0c;或者具有大专学历并通过国家承认的专业技术资格考试。 • 工作年限要…

Python怎么实现模式匹配

什么是模式匹配 模式匹配是一种用于在数据中寻找特定模式或结构的技术。它可以用于识别、查找和提取符合特定模式要求的数据。 在计算机科学中&#xff0c;模式匹配通常用于字符串处理和数据分析领域。一些常见的模式匹配模式包括&#xff1a; 1. 字符串匹配&#xff1a;在一…

【实战】 八、用户选择器与项目编辑功能(上) —— React17+React Hook+TS4 最佳实践,仿 Jira 企业级项目(十四)

文章目录 一、项目起航&#xff1a;项目初始化与配置二、React 与 Hook 应用&#xff1a;实现项目列表三、TS 应用&#xff1a;JS神助攻 - 强类型四、JWT、用户认证与异步请求五、CSS 其实很简单 - 用 CSS-in-JS 添加样式六、用户体验优化 - 加载中和错误状态处理七、Hook&…

Go语言基础语法

Go语言基础语法 Hello World变量&常量定义if 判断语句for 循环语句&#xff08;只有for&#xff09;switch 选择语句数组&#xff08;较少使用&#xff09;切片&#xff08;较多使用&#xff09;map&#xff08;实际最常用&#xff09;range函数指针结构体结构体方法错误处…