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

news2024/10/2 2:53:13

七,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 {



    @Bean
    public 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 {

    @Autowired
    private UserMapper userMapper;

    @Test
    void 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.P6SpyDriver
    url: 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.coloradmin.cn/o/2183635.html

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

相关文章

愿祖国富强!肌肉水凝胶的奥秘,自协调与光驱动,运动模式大揭秘

大家好&#xff0c;在这个国庆佳节&#xff0c;我们一同感受科技的魅力。今天来了解一种特殊的肌肉样水凝胶&#xff0c;它通过自协调形状变化和摩擦调节&#xff0c;能在光的引导下实现多样运动。这一成果为软机器人发展带来新契机——《Light-steered locomotion of muscle-l…

基于ScriptableObject设计游戏数据表

前言 本篇文章是针对之前对于ScriptableObject概念讲解的实际应用之一&#xff0c;在游戏开发中&#xff0c;我们可以使用该类来设计编辑器时的可读写数据表或者运行时的只读数据表。本文将针对运行时的只读数据表的应用进行探索&#xff0c;并且结合自定义的本地持久化存储方式…

一级建造师备考攻略及一建各科老师推荐(各科四大金刚)

吐血整理:真正的实战派一建名师推荐! 考过的同学一定都知道推荐的老师YYDS! 一级建造师各科老师推荐: 《法规》名师:王欣、王竹梅、陈印、关涛 其他老师:房超、蔡恒、刘丹、武海峰、陈洁、安国庆、桂林 《管理》名师:宿吉南、龙炎飞、李向国、朱俊文 其他老师:缴广才、陈晨…

跟《经济学人》学英文:2024年09月28日这期 The curse of the Michelin star

The curse of the Michelin star Restaurants awarded the honour are more likely to close, research finds 原文&#xff1a; The twelve new restaurants added to the New York Michelin Guide this month, serving up cuisine ranging from “haute French” to “eco…

9.数据结构与算法-单链表,循环链表和双向链表的比较////顺序表和链表的比较

单链表&#xff0c;循环链表和双向链表的时间效率比较 顺序表和链表的区别 存储密度

HarmonyOS Next应用开发——自定义组件的使用

自定义组件的使用 在ArkUI中&#xff0c;UI显示的内容均为组件&#xff0c;由框架直接提供的称为系统组件&#xff0c;由开发者定义的称为自定义组件。在进行 UI 界面开发时&#xff0c;通常不是简单的将系统组件进行组合使用&#xff0c;而是需要考虑代码可复用性、业务逻辑与…

达梦数据库开启归档模式

目录 一、什么是归档模式&#xff1f; 二、开启归档模式的步骤 1、创建归档目录 2、进入dm数据库bin目录 3、登录数据库 4、关闭数据库 5、启动数据库到Mount状态 6、增加本地归档日志文件 7、开启归档 8、启动数据库 9、验证是否开启成功 三、开启归档模式的优…

Lj视频下载器 1.1.37 简洁高效的视频下载工具

Lj视频下载器是一个功能强大的视频下载器&#xff0c;支持直接添加视频地址或 m3u8 资源地址&#xff0c;可以从网页中自动提取视频进行下载。支持多种视频格式&#xff0c;包括 m3u8&#xff0c;并能自动检测并移除广告片段。 大小&#xff1a;19M 百度网盘&#xff1a;https…

Linux CentsOS定时删除一个目录下(包含子目录)的改动时间大于12小时的文件

Shell脚本 文件目录如下图 ** 查找/ai/img/目录下的所有文件** find /ai/img/ -type f查找/ai/img/目录下的所有上次改动时间大于720分钟(12小时)的文件 12 小时&#xff0c;也就是 720 分钟。所以&#xff0c;我们可以使用 -mmin 720 来查找修改时间超过 720 分钟&#xff08;…

uniapp 微信小程序 微信支付

本章的内容我尽量描述的细致一些&#xff0c;哪里看不懂给我评论就可以&#xff0c;我看到进行回复 微信支付大致分为4步&#xff0c;具体看后端设计 1. 获取code 2. 根据code获取openid 3. 根据openid&#xff0c;以及部分订单相关数据&#xff0c;生成prepayId (预支付交易会…

免费 Oracle 各版本 离线帮助使用和介绍

文章目录 Oracle 各版本 离线帮助使用和介绍概要在线帮助下载离线文档包&#xff1a;解压离线文档&#xff1a;访问离线文档&#xff1a;导航使用&#xff1a;目录介绍Install and Upgrade&#xff08;安装和升级&#xff09;&#xff1a;Administration&#xff08;管理&#…

交通场景多目标检测系统源码分享

交通场景多目标检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Comput…

Qt界面优化——绘图API

文章目录 绘图核心API绘制各种形状绘制线段绘制矩形绘制圆形绘制文本设置画笔设置画刷 绘制图片 绘图核心API Qt的各种控件&#xff0c;本质上都是画出来的&#xff0c;这不过这些都是提前画好了&#xff0c;我们拿过来直接使用即可。 实际开发中&#xff0c;可能现有控件无法…

面了智谱大模型算法岗,效率贼高!

最近这一两周不少互联网公司都已经开始秋招提前批面试了。 不同以往的是&#xff0c;当前职场环境已不再是那个双向奔赴时代了。求职者在变多&#xff0c;HC 在变少&#xff0c;岗位要求还更高了。 最近&#xff0c;我们又陆续整理了很多大厂的面试题&#xff0c;帮助一些球友…

使用容器启动的zk无法暴露3888问题解决

1. 问题描述 zk配置如下&#xff1a; 我通过容器启动了一个zk&#xff0c;通过-p 参数暴露了2181和3888端口&#xff0c;容器启动脚本如下&#xff1a; #!/bin/shdocker rm -f myzookeeper1docker run -p 12181:2181 -p 13888:3888 --name myzookeeper1 --restart always …

C# 字符串(String)的应用说明一

一.字符串&#xff08;String&#xff09;的应用说明&#xff1a; 在 C# 中&#xff0c;更常见的做法是使用 string 关键字来声明一个字符串变量&#xff0c;也可以使用字符数组来表示字符串。string 关键字是 System.String 类的别名。 二.创建 String 对象的方法说明&#x…

c++ 使用 Graham 扫描的凸包(Convex Hull using Graham Scan)

先决条件&#xff1a; 如何检查两个给定的线段是否相交&#xff1f; c https://blog.csdn.net/hefeng_aspnet/article/details/141713655 java https://blog.csdn.net/hefeng_aspnet/article/details/141713762 python https://blog.csdn.net/hefeng_aspnet/article/details/…

Australis 相機率定軟體說明

概要 課堂中使用Australis這套軟體&#xff0c;順帶記錄操作過程 內容以老師口述及我測試的經過 照片為老師課堂提供之 說明 執行 Step1. 匯入照片 注意&#xff01;&#xff01;如果是Mac的作業系統&#xff0c;將資料夾移到Windows上的時候&#xff0c;建議創一個新的資料…

mysql---索引类型及索引方法使用

mysql索引类型 Normal、Full Text、Unique 在 MySQL 中&#xff0c;索引的类型主要有以下几种&#xff1a; Normal Index&#xff08;普通索引&#xff09;&#xff1a; 这是最基本的索引类型&#xff0c;没有唯一性要求。允许重复值&#xff0c;可以加速查询性能。用法&#…

产品经理的学习

初学 接需求 画原型 写文档 日常产出 流程图 举例购物的流程 结构图 一个应用的全部功能&#xff0c;用思维导图的方式去罗列出来 竞品分析文档 竞品分类 竞品选择 竞品采集 竞品文档书写 也可以做一个产品的产品结构图 需求文档 干系人 需求方 记录人 产品经理 其他项目干系人…