七,MyBatis-Plus 扩展功能:乐观锁,代码生成器,执行SQL分析打印(实操详细使用)

七,MyBatis-Plus 扩展功能:乐观锁,代码生成器,执行SQL分析打印(实操详细使用)

文章目录

  • 七,MyBatis-Plus 扩展功能:乐观锁,代码生成器,执行SQL分析打印(实操详细使用)
  • 1. 乐观锁
  • 2. 代码生成器
  • 3. 执行SQL分析打印
  • 4. 总结:
  • 5. 最后:

1. 乐观锁

首先我们需要先了解开发中的一个常见场景,叫做并发请求。

并发请求就是在同一时刻有多个请求,同时请求服务器资源,如果是获取信息,没什么问题,但是如果是对于信息做修改操作,那就会出现问题。

这里我们举一个例子。比如:目前商品的库存只剩余 1件了,这个时候有多个用户都想要购买这件商品,都发起了购买商品的请求,那么能让这多个用户都购买到么,肯定是不行的,因为多个用户都买到了这件商品,那么就会出现超卖问题,库存不够时没法发货的。所以在开发中就要解决这种超卖的问题。

在这里插入图片描述

抛开超卖的这一种场景,诸如此类并发访问的场景非常多,这类场景的核心问题就是,一个请求在执行的过程中,其他请求不能改变数据,如果是一次完整的请求,在该请求的过程中其他请求没有对于这个数据产生修改操作,那么这个请求时能够正常修改数据的。如果该请求在改变数据的过程中,已经有其他请求改变了数据,那该请求就不去改变这条数据了。

在这里插入图片描述

想要解决这类问题,最常见的就是加锁的思想,锁可以用验证在请求的执行过程中,是否有数据发生改变。

常见的数据库锁类型有两种,悲观锁和乐观锁。

一次完成的修改操作是:先查询数据,然后修改数据。

这样做的操作能够保证读取到的信息就是当前的信息,保证了信息的正确性,但是并发效率很低,在实际开发中使用悲观锁的场景很少,因为在并发时,我们是要保证效率的。

乐观锁: 乐观锁是通过表字段完成设计的,他的核心思想是,在读取的时候不加锁,其他请求依然可以读取到这个数据,在修改的时候判断一个数据是否有被修改过,如果有被修改过,那本次请求的修改操作失败。

具体的通过 SQL 是这样实现的,添加了一个 where version = 1

这样做的操作是不会对于数据读取产生影响,并发的效率较高,但是可能目前看到的数据并不是真实信息数据,是被修改之前的,但是在很多场景下是可以容忍的,并不是产生很大影响。例如:很多时候我们看到的是有库存,或者都加入都购物车,但是点进去以后库存没有了。

在数据库表中添加一个字段 version,表示版本,默认值是1

在这里插入图片描述

生成后的效果

在这里插入图片描述

找到实体类,添加对应的属性,并使用 @Version标注 为这是一个乐观锁字段信息。

在这里插入图片描述

因为要对每条修改语句完成语句的增强,这里我们通过拦截器的配置,让每条修改的 sql 语句在执行的时候,都加上版本控制的功能。

在这里插入图片描述

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.apache.ibatis.plugin.Interceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MybatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();/*通过配置类来指定一个具体数据库的分页插件,因为不同的数据库的方言不同,具体涩会给你从的分页语句也会不同,这里我们指定数据库为 MySQL数据库*/mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); // 乐观锁return mybatisPlusInterceptor;}}

测试效果,这里我们模拟先查询,再修改

@Test
void updateTest(){User user = userMapper.selectById(6L);user.setName("li");userMapper.updateById(user);
}

在这里插入图片描述

我们通过查看拼接好的SQL语句发现,查询时将User的数据查询出来,是包含version版本信息的

在这里插入图片描述

当我们完成修改时,他会将版本号 + 1

此时查看数据发现,更改姓名后,version已经为2了

在这里插入图片描述

接下来我们模拟一下,当出现多个修改请求的时候,是否能够做到乐观锁的效果。

乐观锁的效果是,一个请求在修改的过程中,是允许另一个请求查询的,但是修改时会通过版本号是否改变来决定是否修改,如果版本号变了,证明已经有请求修改过数据了,那这次修改不生效,如果版本号没有发生变化,那就完成修改。

在这里插入图片描述

package com.rainbowsea;import com.rainbowsea.bean.User;
import com.rainbowsea.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
public class LockTest {@Autowiredprivate UserMapper userMapper;@Testvoid updateTest2() {// 模拟操作1的查询操作User user1 = userMapper.selectById("5");System.out.println("查询结果:" + user1);// 模拟操作2的查询操作User user2 = userMapper.selectById("5");System.out.println("查询结果:" + user2);// 模拟操作2的修改操作user2.setName("liHua");userMapper.updateById(user2);// 模拟操作1的修改操作user1.setName("zhangsan");userMapper.updateById(user1);}}

我们来看下这段代码的执行过程,这段代码其实是两次操作,只不过操作1在执行的过程中,有操作2完成了对于数据的修改,这时操作1就无法再次进行修改了

操作1的查询:此时版本为2

在这里插入图片描述

操作2的查询:此时版本为2

在这里插入图片描述

操作2的修改:此时检查版本,版本没有变化,所以完成修改,并将版本改为3

在这里插入图片描述

在这里插入图片描述

操作1的修改:此时检查版本,版本已经有最初获取的版本信息发生了变化,所以杜绝修改

在这里插入图片描述

2. 代码生成器

代码生成器和逆向工程的区别在于,代码生成器可以生成更多的结构,更多的内容,允许我们能够配置生成的选项更多。在这里我们演示一下代码生成器的用法。

参考官网,使用代码生成器需要引入两个依赖;

在这里插入图片描述

  <!--        mybatis-plus 的依赖--><!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3</version></dependency><!--freemarker模板依赖--><dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.31</version></dependency>

编写代码生成器代码

@SpringBootTest
class GeneratorApplicationTests {public static void main(String[] args) {FastAutoGenerator.create("jdbc:mysql://localhost:3306/mybatisplus?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false", "root", "root").globalConfig(builder -> {builder.author("powernode") // 设置作者//.enableSwagger() // 开启 swagger 模式.fileOverride() // 覆盖已生成文件.outputDir("D://"); // 指定输出目录}).packageConfig(builder -> {builder.parent("com.powernode") // 设置父包名.moduleName("mybatisplus") // 设置父包模块名.pathInfo(Collections.singletonMap(OutputFile.xml, "D://")); // 设置mapperXml生成路径}).strategyConfig(builder -> {builder.addInclude("powershop_user") // 设置需要生成的表名.addTablePrefix("powershop"); // 设置过滤表前缀}).templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板.execute();}
}

执行,查看生成效果

3. 执行SQL分析打印

在我们日常开发工作当中,避免不了查看当前程序所执行的SQL语句,以及了解它的执行时间,方便分析是否出现了慢SQL问题。我们可以使用MybatisPlus提供的SQL分析打印的功能,来获取SQL语句执行的时间。

由于该功能依赖于 p6spy 组件,所以需要在 pom.xml 中先引入该组件。

在这里插入图片描述

<dependency><groupId>p6spy</groupId><artifactId>p6spy</artifactId><version>3.9.1</version>
</dependency>

application.yml中进行配置

将驱动和 url 修改

spring:datasource:driver-class-name: com.p6spy.engine.spy.P6SpyDriverurl: jdbc:p6spy:mysql

在这里插入图片描述

resources下,创建 spy.properties 配置文件。

在这里插入图片描述

#3.2.1以上使用modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory# 自定义日志打印
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger#日志输出到控制台
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger# 使用日志系统记录 sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger# 设置 p6spy driver 代理
deregisterdrivers=true# 取消JDBC URL前缀
useprefix=true# 配置记录 Log 例外,可去掉的结果集error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories=info,debug,result,commit,resultset# 日期格式
dateformat=yyyy-MM-dd HH:mm:ss# 实际驱动可多个
#driverlist=org.h2.Driver# 是否开启慢SQL记录
outagedetection=true# 慢SQL记录标准 2 秒
outagedetectioninterval=2

测试

执行查询所有的操作,可以看到sql语句的执行时间

在这里插入图片描述

4. 总结:

  1. 注意:理解悲观锁和乐观锁:
    1. 悲观锁: 悲观锁是在查询的时候就锁定数据,在这次请求未完成之前,不会释放锁。必须等到这次请求执行完毕以后,再释放掉锁,释放了锁之后,其他请求才可以对于这条数据完成读写。
    2. 乐观锁: 乐观锁是通过表字段完成设计的,他的核心思想是,在读取的时候不加锁,其他请求依然可以读取到这个数据,在修改的时候判断一个数据是否有被修改过,如果有被修改过,那本次请求的修改操作失败。

5. 最后:

“在这个最后的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。”

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【卡尔曼滤波】 Kalman Filter 原理详解与公式推导

【卡尔曼滤波】 Kalman Filter 原理详解与公式推导 前言引例&#xff1a;什么是卡尔曼滤波&#xff1f;图解卡尔曼滤波引入从宏观上理解卡尔曼融合从微观上理解状态矩阵先验状态矩阵观测状态矩阵 卡尔曼滤波公式理解参数说明预测阶段&#xff08;Prediction&#xff09;更新阶段…

生信初学者教程(二十):免疫浸润分析

文章目录 介绍加载R包导入数据所需函数堆积图箱线图热图相关性矩阵图输出结果总结介绍 在本章节中,将详细探讨免疫细胞的组成结构、其在不同个体和分组之间的相对丰度差异,并通过热图等可视化手段,对这些差异进行直观而深入的解析。这些分析将有助于科研人员更好地理解免疫细…

L0-Linux-关卡材料提交

SSH全称Secure Shell&#xff0c;中文翻译为安全外壳&#xff0c;它是一种网络安全协议&#xff0c;通过加密和认证机制实现安全的访问和文件传输等业务。SSH 协议通过对网络数据进行加密和验证&#xff0c;在不安全的网络环境中提供了安全的网络服务。 SSH 是&#xff08;C/S…

IDE 使用技巧与插件推荐全面指南

目录 目录 常用IDE概述 Visual Studio Visual Studio Code IntelliJ IDEA PyCharm Eclipse IDE 使用技巧 通用技巧 Visual Studio 专属技巧 Visual Studio Code 专属技巧 IntelliJ IDEA 专属技巧 插件推荐 Visual Studio 插件 Visual Studio Code 插件 IntelliJ…

《如何高效学习》

有道云笔记 第一部分 整体性学习策略 结构 结构就像思想中的一座城市&#xff0c;有很多建筑物&#xff0c;建筑物之间有道路相连&#xff0c;有高大而重要的与其他建筑有上百条路相连&#xff0c;无关紧要的建筑只有少数泥泞的小道与外界相通。 建立良好的知识结构就是绘制…

掌握这12招,ChatGPT秒变你的高效神器!

近期&#xff0c;围绕ChatGPT和人工智能的讨论热度有所减退&#xff0c;OpenAI的更新频率也显著降低。在此阶段&#xff0c;我们可以沉下心来&#xff0c;进行总结与反思&#xff0c;无需担心错失热点&#xff0c;而应专注于更有效地将AI整合进我们的工作流。 背景&#xff1a;…

2024/10/1 操作系统大题专训之文件

2022&#xff1a; 2018&#xff1a; 2016&#xff1a; 2014&#xff1a; 2012&#xff1a; 2011&#xff1a;

postgresql僵尸进程的处理思路

简介 僵尸进程&#xff08;zombie process&#xff09;是指一个已经终止但仍然在进程表中保留条目的进程。正常情况下&#xff0c;当一个进程完成执行并退出时&#xff0c;操作系统会通过父进程调用的wait()或waitpid()系统调用来收集该子进程的退出状态。如果父进程未及时调用…

DICOM文件的格式详细解说(1)

1 DICOM的详细介绍 DICOM要到这里面看Current Edition&#xff0c;这是标准委员会制定的标准&#xff0c;同时也在与时俱进&#xff0c;不断的进行新的数据格式更新。 2 DICOM的格式 图1 DICOM文件格式的图示 要先说一下数据结构&#xff0c;我们被最多影响的是数据结构和算…

Trilium Notes笔记本地化部署与简单使用指南打造个人知识库

文章目录 前言1. 安装docker与docker-compose2. 启动容器运行镜像3. 本地访问测试4.安装内网穿透5. 创建公网地址6. 创建固定公网地址 前言 今天和大家分享一款在G站获得了26K的强大的开源在线协作笔记软件&#xff0c;Trilium Notes的中文版如何在Linux环境使用docker本地部署…

贝励德故事:注册电气工程师有多难考?(知乎)

之所以说是条不归路&#xff0c;给你看看我的复习资料就知道了 这是需要买的手册和规范&#xff0c;加起来有五十斤重了。你还得在三小时内找到知识点结合题意计算作答&#xff0c;计算器不能出一点差错。这个难度可想而知。 这是我备考两年多做过的题&#xff0c;看过的总结&a…

Spring Boot框架下的足球青训俱乐部管理

2 相关技术简介 2.1 Java技术 Java是一门伟大的纯面向对象的编程语言和编程语言。同时&#xff0c;它还是Java语言从嵌入式开发到企业级开发的平台。Java凭借其一次编译&#xff0c;任何地方执行的优点&#xff0c;使得盛行的web应用程序有大量的Java编译&#xff0c;很好地支…

AMD CDNA™2 GPU 中的寄存器压力

Register pressure in AMD CDNA™2 GPUs — ROCm Blogs 注意&#xff1a; 此博客以前是 AMD实验室笔记 博客系列的一部分。 GPU kernel 中的寄存器压力对高性能计算 (HPC) 应用程序的整体性能有着巨大的影响。理解和控制寄存器的使用可以让开发者精心设计代码&#xff0c;以最…

jQuery——元素尺寸

1、内容尺寸 height&#xff08;&#xff09;&#xff1a;height width&#xff08;&#xff09;&#xff1a;width 2.内部尺寸 innerHeight&#xff08;&#xff09;&#xff1a;height padding innerWidth&#xff08;&#xff09;&#xff1a;width padding 3、外部尺寸…

MES数据的集成方式

为了实现与其他关键系统的数据共享和协同工作&#xff0c;不同的集成方式应运而生。MES系统与其他系统的常见集成模式&#xff0c;包括封装接口调用模式、直接集成模式、数据聚合模型、中间件集成模式以及XML的信息集成模式等。 1. 封装接口调用模式 封装接口调用是一种常见的…

2024年9月中国干旱监测报告(FYDI-2.0指数)

目录 引言 旱情监测与分析 资料来源 引言 2024年9月&#xff0c;北方的降水逐渐增多&#xff0c;进入华西秋雨集中期&#xff0c;从青藏高原北部一直延伸到东北多地&#xff0c;常出现大范围的云带&#xff0c;西北地区的降雨强度较大。南方地区降水分布不均&#xff0c;受…

如何测试网络质量?

如何测试网络质量&#xff1f; 通过百度网盘分享的文件&#xff1a;winMTR 链接&#xff1a;https://pan.baidu.com/s/1Zfw4jciNhng35nfwBlF75Q 提取码&#xff1a;6622 –来自百度网盘超级会员V2的分享 下载WINMTR工具&#xff0c;在启动处输入www.baidu.com 判断方法&…

企业数字化转型的深层次问题与战略解读——基于TOGAF框架的深入分析与解决方案

数字化转型的必然性与复杂性 随着全球化和技术进步的推动&#xff0c;数字化转型成为企业保持竞争力、提升效率、满足客户需求的重要战略选择。然而&#xff0c;数字化转型并不仅仅是技术的简单引入&#xff0c;它涉及到业务模式、运营流程、组织架构以及企业文化的深刻变革。…

成都大学体育场馆预约系统—计算机毕业设计源码37087

摘 要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&#xff0c;科学化的管理&#xff0c;使信息存…

软件开发人员绩效考核方案(参考)

1、产品&运营绩效考核表 2、开发绩效考核表 3、测试绩效考核表 4、CPI指标库 软件全套资料部分文档清单&#xff1a; 工作安排任务书&#xff0c;可行性分析报告&#xff0c;立项申请审批表&#xff0c;产品需求规格说明书&#xff0c;需求调研计划&#xff0c;用户需求调查…