【MyBatis-Plus】进阶之乐观锁、悲观锁逻辑删除分页和查询构造器的使用

目录

一、乐观锁、悲观锁

1、什么是乐观锁和悲观锁

①乐观锁(Optimistic Locking):

②悲观锁(Pessimistic Locking):

③实现方式

2、乐观锁和悲观锁的区别

①乐观锁(Optimistic Locking)

②悲观锁(Pessimistic Locking)

③总结

3、案例

①如何实现乐观锁?

②如何使用MyBatis-Plus实现乐观锁?

二、逻辑删除

1、什么是逻辑删除

2、为什么使用逻辑删除

3、案例

①官方说明

②配置方式

③演示

三、分页和查询构造器

1、查询构造器

2、分页(PaginationInnerInterceptor)


一、乐观锁、悲观锁

1、什么是乐观锁和悲观锁

①乐观锁(Optimistic Locking):

  1. 乐观锁假设多个事务在大多数情况下不会相互冲突,因此在数据读取时不会立即加锁。
  2. 数据需要更新时,会检查在此期间是否有其他事务对该数据进行过修改。如果,则当前事务会失败并回滚
  3. 乐观锁通常通过版本号或时间戳来实现,其中读取数据时获取版本号或时间戳,更新数据时检查版本号或时间戳是否发生变化。

②悲观锁(Pessimistic Locking):

  1. 悲观锁则相反,它假设多个事务在大多数情况下会相互冲突,因此在数据读取时就直接加锁
  2. 这意味着其他事务在加锁释放之前无法访问该数据
  3. 悲观锁可以通过数据库的行级锁、表级锁等方式实现。

③实现方式

  • 乐观锁: MyBatis Plus 支持使用 Version 注解实现乐观锁。在实体类中,可以添加一个版本字段并使用 Version 注解来标记为乐观锁字段。在更新操作时,MyBatis Plus 会自动检查版本号是否发生变化,以决定是否允许更新。
  • 悲观锁: MyBatis Plus 提供了 Lock 注解支持悲观锁。当需要在更新操作时对记录加锁时,可以使用 Lock 注解标记对应的 SQL 语句。这会在执行该 SQL 语句时自动加锁,以确保数据的一致性。

2、乐观锁和悲观锁的区别

①乐观锁(Optimistic Locking)

  1. 操作数据时持乐观态度,认为数据在并发操作期间不太可能被其他事务修改,因此不会立即加锁
  2. 更新数据时,会检查在此期间是否有人修改了数据。如果检测到数据已被修改,则放弃更新操作否则,执行更新
  3. 乐观锁适用于读操作频繁、写操作较少的场景,因为不加锁的特性在性能方面可能优于悲观锁

②悲观锁(Pessimistic Locking)

  1. 在操作数据时持悲观态度,认为数据在并发操作期间很可能被其他事务修改。
  2. 因此,在读取数据时就直接对数据进行加锁,防止其他事务同时修改,直到当前事务完成操作并释放锁。
  3. 悲观锁适用于写操作频繁的场景,可以避免因数据被其他事务修改而导致的冲突。

③总结

  1. 加锁时间不同:乐观锁在读取数据时不会对其加锁,而是在写入时进行比较和加锁操作;悲观锁在读取数据时就会对其加锁。

  2. 冲突处理方式不同:乐观锁会在写入时进行比较和冲突检测,如果版本号不一致则操作失败,需要重新读取数据;悲观锁则会阻塞其他进程对该数据的访问,直到当前进程完成操作并解锁。

  3. 适用场景不同:乐观锁适用于并发量比较小、数据量比较大、操作更多为读取的场景;悲观锁适用于并发量比较大、数据量比较小、操作更多为写入的场景。

3、案例

①如何实现乐观锁?

@Version注解标记乐观锁,通过 version 字段来保证数据的安全性,当修改数据的时候,会以 version 作为条件,当条件成立的时候才会修改成功。

1)取出记录时,获取当前 version

2)更新时,带上这个 version

3)执行更新时,`update tableName set version = oldVersion + 1 where version = oldVersion`

4)如果 version 不对,就更新失败

②如何使用MyBatis-Plus实现乐观锁?

  1. 给数据库表添加 version 字段,并设置默认值为1
  2. 实体类增加 version 属性,并添加 @Version 注解
        /**
         * 乐观锁
         */
        @Version
        private Integer version;
  3. 配置乐观锁插件
    @Configuration
    public class MybatisPlusConfig {
    
        /**
         * 添加分页插件
         * 乐观锁插件
         */
        @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor() {
            MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    //        乐观锁插件
            interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
            return interceptor;
        }
    }

     
  4. 测试
        @Test
        void contextLoads() {
            //先查询,再修改
            Book book = bookMapper.selectById("1685091066406");
            book.setBookname("Java编程思想");
            book.setPrice(100f);
            bookMapper.updateById(book);
        }
    从控制台的日志信息发现:修改数据时 version 作为条件判断,并且 version 自动完成自增操作,即:version = version+1

    测试多线程下乐观锁失败:
    @Test
    public void demo2(){
        //线程1:
        Book book1 = bookMapper.selectById("1685091066406");
        book1.setBookname(".Net之入门");
        book1.setPrice(110f);
    
        //线程2:(在线程1的修改操作未来得及执行时介入)
        Book book2 = bookMapper.selectById("1685091066406");
        book2.setBookname("Python之入门");
        book2.setPrice(200f);
        bookMapper.updateById(book2);
    
        //如果没有乐观锁就会覆盖插队线程的值!
        bookMapper.updateById(book1);//更新失败
    }

总结:就是一次

二、逻辑删除

1、什么是逻辑删除

        逻辑删除是指文件没有被真正的删除,只不过是文件名的第一个字节被改成操作系统无法识别的字符。这种删除操作通常是可逆的,也就是说,用适当的工具或软件可以把删除的文件恢复出来。逻辑删除和物理删除是两种不同的文件删除方式。在计算机中,资料数据等都以文件形式存储。当文件需要被删除时,可以根据实际需求选择逻辑删除或物理删除

2、为什么使用逻辑删除

原因、作用:

  1. 数据恢复:逻辑删除只是修改了文件名或其他元数据,并没有真正删除数据。因此,被删除的数据仍然存在于存储介质中,可以被恢复。这种设计方便数据恢复,保护了数据本身的价值。
  2. 保护数据完整性:逻辑删除操作不会对数据本身造成损害,从而保护了数据的完整性。
  3. 操作简单:逻辑删除操作相对简单,只需修改元数据即可,而无需清空存储介质或进行其他复杂操作。
  4. 灵活性高:逻辑删除允许在将来某个时间点恢复被删除的数据,因此具有很高的灵活性。
  5. 减少存储空间占用:物理删除需要清空存储介质,可能会浪费大量的存储空间。相比之下,逻辑删除不会占用额外存储空间。
  6. 满足法规和政策要求:在某些行业或应用场景中,法规和政策可能要求保留被删除的数据,以便进行审计或追溯。逻辑删除可以满足这些要求,而不会造成数据丢失。

3、案例

①官方说明

只对自动注入的 sql 起效:

  • 插入: 不作限制
  • 查找: 追加 where 条件过滤掉已删除数据,如果使用 wrapper.entity 生成的 where 条件也会自动追加该字段
  • 更新: 追加 where 条件防止更新到已删除数据,如果使用 wrapper.entity 生成的 where 条件也会自动追加该字段
  • 删除: 转变为 更新

例如:

  • 删除: update user set deleted=1 where id = 1 and deleted=0
  • 查找: select id,name,deleted from user where deleted=0

字段类型支持说明:

  • 支持所有数据类型(推荐使用 Integer,Boolean,LocalDateTime)
  • 如果数据库字段使用datetime,逻辑未删除值和已删除值支持配置为字符串null,另一个值支持配置为函数来获取值如now()

附录:

  • 逻辑删除是为了方便数据恢复和保护数据本身价值等等的一种方案,但实际就是删除。
  • 如果你需要频繁查出来看就不应使用逻辑删除,而是以一个状态去表示。

②配置方式

全局配置

例: application.yml

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

在对应的实体类中添加逻辑删除字段,如下:

    //逻辑删除
    @TableField("statu")
    private Integer statu;

局部配置

请在实体类对应的逻辑删除属性上加入@TableLogic注解。其中@TableLogic注解属性介绍如下:

属性名类型说明
valueString未逻辑删除的值
delvalString已逻辑删除的值

在实体类上配置逻辑删除字段,如下:

/**
* 逻辑删除,1=删除,0=正常
*/
@TableLogic(value = "0",delval = "1")
@TableField("statu")
private Integer statu;

③演示

创建junit测试,使用deleteById方法进行测试。

    @Test
    void contextLoads() {
            //先使用deleteById删除对应的数据
            bookMapper.deleteById("493783504224325");
            //使用查询方法查询数据
            //List<Book> books = bookMapper.selectList(null);
            //books.forEach(System.out::println);
    }

观察idea控制台输出结果,会发现执行deleteById方法后,不再显示delete语句,而是update语句。则表示逻辑删除成功,可查看MySQL数据表中的结果。

然后,执行selectList(null)方法,可发现查询语句的where条件后加入逻辑删除字段deleted=0的判断处理,表示只查询出未逻辑删除的数据。

三、分页和查询构造器

1、查询构造器

QueryWrapper是Mybatis-Plus提供的一个条件构造器,用于快速构建SQL查询语句的条件部分。通过使用QueryWrapper,我们可以方便地进行单表数据的查询、修改、删除等操作。

QueryWrapper的语法类似于Mybatis的XML文件中的where标签,其最终会被转换为SQL语句的条件部分。我们可以通过链式调用的方式,不断添加查询条件,从而构建出复杂的查询条件。

2、分页(PaginationInnerInterceptor)

支持的数据库

  • mysql,oracle,db2,h2,hsql,sqlite,postgresql,sqlserver,Phoenix,Gauss ,clickhouse,Sybase,OceanBase,Firebird,cubrid,goldilocks,csiidb,informix,TDengine,redshift

  • 达梦数据库,虚谷数据库,人大金仓数据库,南大通用(华库)数据库,南大通用数据库,神通数据库,瀚高数据库,优炫数据库,星瑞格数据库

配置分页插件

@Configuration
public class MyBatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        //注册分页插件
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return mybatisPlusInterceptor;
    }
}

实现分页

int page=1;
int row=10;
//条件构造器
QueryWrapper<Book> wrapper=new QueryWrapper<>();
//设置条件
//TODO
//设置分页
Page<Book> result = bookMapper.selectPage(new Page<Book>()
                .setCurrent(page)
                .setSize(row)
                , wrapper);
List<Book> records = result.getRecords();
System.out.println("总记录数:"+result.getTotal());
records.forEach(System.out::println);

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【头歌实训】PySpark Streaming 数据源

文章目录 第1关&#xff1a;MySQL 数据源任务描述相关知识PySpark JDBC 概述PySpark JDBCPySpark Streaming JDBC 编程要求测试说明答案代码 第2关&#xff1a;Kafka 数据源任务描述相关知识Kafka 概述Kafka 使用基础PySpark Streaming Kafka 编程要求测试说明答案代码 第1关&a…

亿赛通电子文档安全管理系统 linkfilterservice 未授权漏洞

产品简介 亿赛通电子文档安全管理系统&#xff0c;&#xff08;简称&#xff1a;CDG&#xff09;是一款电子文档安全加密软件&#xff0c;该系统利用驱动层透明加密技术&#xff0c;通过对电子文档的加密保护&#xff0c;防止内部员工泄密和外部人员非法窃取企业核心重要数据资…

在Spring Cloud中使用Ribbon完成一个简单的负载均衡demo

Spring Cloud系列断更了有一段时间了&#xff0c;这段时间最近都在忙着项目上的事&#xff0c;天天修复bug以及调整需求&#xff0c;反正各种操劳&#xff0c;了解业务需求&#xff0c;然后开发相关功能&#xff0c;很久都没碰Spring Cloud系列的相关文章了&#xff0c;最近回头…

ASP.Net实现新闻添加查询(三层架构,含照片)

目录 演示功能&#xff1a; 点击启动生成页面 点击搜索模糊查询 点击添加跳转新界面 ​编辑 点击Button添加 步骤&#xff1a; 1、建文件 ​编辑 2、添加引用关系 3、根据数据库中的列写Models下的XueshengModels类 4、DAL下的DBHelper&#xff08;对数据库进行操作…

Win10电脑蓝牙默认音量100的设置教程

在Win10电脑操作过程中&#xff0c;用户想设置连接蓝牙后音量默认是100&#xff0c;但不知道具体的设置操作步骤。这时候用户需要打开Win10系统上的注册表&#xff0c;点击修改注册表来完成这一设置&#xff0c;下面就是Win10电脑蓝牙默认音量100的设置教程介绍&#xff0c;帮助…

【网络安全 | 指纹识别工具】WhatWeb使用详析

前言 WhatWeb 是一款用于识别 Web 应用程序和 Web 服务器的开源工具。它可以识别网站使用的编程语言、Web 框架、Web 服务器软件、Web 应用程序等信息&#xff0c;从而帮助安全测试人员快速了解目标网站的技术特征&#xff0c;发现可能存在的漏洞。 本文将对 WhatWeb 的使用方法…

使用Rust发送邮件

SMTP协议与MIME协议 SMTP&#xff08;简单邮件传输协议,Simple Mail Transfer Protocol&#xff09;是一种用于发送和接收电子邮件的互联网标准通信协议。它定义了电子邮件服务器如何相互发送、接收和中继邮件。SMTP 通常用于发送邮件&#xff0c;而邮件的接收通常由 POP&#…

在wps里导入Mathtype、改变字体

1 在wps里导入Mathtype 开发工具--加载项 2. 在“模板和加载项”窗口中再点击“添加” 3.找到mathtype安装路径下面的“OfficeSupprot”&#xff0c;这时会看到有“32”和“64”两个文件夹&#xff0c;分别对应WPS软件的系统&#xff08;任务管理器可以直接查看wps版本&#x…

three.js实现3D汽车展厅效果展示

项目搭建 本案例还是借助框架书写three项目&#xff0c;借用vite构建工具搭建vue项目&#xff0c;搭建完成之后&#xff0c;用编辑器打开该项目&#xff0c;在终端执行 npm i 安装一下依赖&#xff0c;安装完成之后终端在安装 npm i three 即可。 因为我搭建的是vue3项目&…

理解 Go Mod Init

初始化Go模块和管理依赖的全面指南 go mod init 是Go编程语言&#xff08;通常称为Golang&#xff09;中用于初始化新Go模块的命令。在Go中&#xff0c;一个模块是一组相关的Go包&#xff0c;它们作为一个单元一起进行版本控制。通常&#xff0c;在项目目录的根目录下使用 go m…

NLP论文阅读记录 - 01 | 2021 神经抽象摘要方法及摘要事实一致性综述

文章目录 前言0、论文摘要一、Introduction二.背景2.1自动总结任务2.2 数据集DUC-2004Gigaword [Graff et al., 2003, Napoles et al., 2012]CNN/DailyMail [Nallapati 等人&#xff0c;2016]XSum [Narayan 等人&#xff0c;2018] 2.3 摘要系统的评估2.3.1 Rouge [Lin, 2004] 三…

用编程解决习题【计算机图像处理】

用编程解决习题【计算机图像处理】 前言版权第三章 03采样量化与像素间关系作业编程 第六章 06图像的直方图变换作业编程 第七章 07图像的噪声抑制作业编程 第十章 10二值图像的分析作业编程 最后 前言 2023-12-27 21:11:27 以下内容源自《【计算机图像处理】》 仅供学习交流…

CSS3用户界面弹性盒子

CSS3用户界面 resize 该CSS3属性用于定义元素是否应该调整大小&#xff0c;如果需要调整大小&#xff0c;那么以哪个轴进行调整。 语法&#xff1a;resize:both | horizontal | none | vertical 注意&#xff1a;该属性仅应用在overflow值而不是visible的元素上。通常而言&am…

《国货之光》-粗粮八宝粉

国潮正当时&#xff0c;好物当自强。赋能国货品牌&#xff0c;打造行业爆品。今天为大家带来的国货好物是老磨坊纯杂粮八宝粉 小时候&#xff0c;经常听妈妈说&#xff0c;要多吃杂粮&#xff0c;对身体好。然后每天不重样的给我做杂粮饭菜。不知道大家有没有和我相同的经历。…

Windows搭建FTP服务器教学以及计算机端口介绍

目录 一. FTP服务器介绍 FTP服务器是什么意思&#xff1f; 二.Windows Service 2012 搭建FTP服务器 1.开启防火墙 2.创建组 ​编辑3.创建用户 4.用户绑定组 5.安装ftp服务器 ​编辑6.配置ftp服务器 7.配置ftp文件夹的权限 8.连接测试 三.计算机端口介绍 什么是网络…

单集群400TB,OceanBase稳定支撑快手核心业务场景

一款日均超过千万人访问的短视频 App 快手&#xff0c;面对高并发流量如何及时有效地处理用户请求&#xff1f;通过在后端配置多套 MySQL 集群来支撑高流量访问&#xff0c;以解决大数据量存储和性能问题&#xff0c;这种传统的 MySQL 分库分表方案有何问题&#xff1f;快手对分…

c语言结构体数组

使用结构体变量建立数据类型后&#xff0c;我们就可以利用这个数据类型创建数组&#xff0c;就比如创建整形数组就可以写为 int arr[ ],那么创建一个自己建立的数据类型的数组就可以写为&#xff1a; 声明的结构体类型名 数组名。 例如我们声明一个结构体类型struct my后&am…

技术扫盲:如何优雅的使用 java -jar

java -jar xxx.jar java -jar 是一个用于在命令行界面中执行 Java 可执行 JAR 文件的命令。它的语法如下&#xff1a; java -jar <JAR 文件路径> [参数]其中&#xff1a; java 是 Java 运行时环境的可执行文件。-jar 是一个选项&#xff0c;表示要执行的文件是一个 JA…

文件IO

文章目录 文章目录 前言 一 . 文件 文件路径 文件类型 Java中操作文件 File 概述 属性 构造方法 方法 createNewFile mkdir 二 . 文件内容的读写 - IO InputStream 概述 FileInputStream 概述 利用 Scanner 进行字符读取 OutputStream 概述 PrintWriter封装O…

【教学类-42-03】20231225 X-Y 之间加法题判断题3.0(确保错误题有绝对错误的答案)

背景需求&#xff1a; 根据需求&#xff0c;0-5以内的判断是21题正确&#xff0c;21题错误&#xff0c;但由于错误答案是随机数抽取&#xff0c;有可能恰好是正确的&#xff0c;所以会出现每套题目的正确数和错误数不一样的情况 优化思路一&#xff1a; 设置如果错误答案与正…