MyBatis-Plus的进阶:乐观锁和悲观锁、逻辑删除、分页和查询构造器

目录

1.乐观锁和悲观锁

1.1.什么是乐观锁和悲观锁

1.2.乐观锁和悲观锁的区别

1.3.综合案例

2.逻辑删除

2.1.什么是逻辑删除

2.2.为什么使用逻辑删除

2.3.综合案例

2.3.1.官方提示

2.3.2.配置方式

2.3.3.案例演示

3.分页和查询构造器

3.1.查询构造器

3.2.分页


1.乐观锁和悲观锁

1.1.什么是乐观锁和悲观锁

乐观锁( Optimistic Locking )悲观锁是数据库中的两种并发控制机制。

乐观锁假定数据一般情况下不会发生冲突,因此在读取数据时不会对其加锁,而是在写入时先比较数据版本号(比如时间戳)是否相同,再进行操作。如果版本号相同,则表示该数据没有被其他进程修改,可以进行写操作;如果版本号不同,则表示该数据已经被其他进程修改,写操作会失败,需要重新读取数据进行操作。

乐观锁是为了解决并发过程中数据更新冲突的问题,乐观锁能提高并发过程中的程序吞吐量。

悲观锁则假定数据会发生冲突,因此在读取数据时就会对其加锁,防止其他进程同时修改此数据,直到当前进程操作完成并解锁后,其他进程才能再次操作该数据。

1.2.乐观锁和悲观锁的区别

乐观锁悲观锁的区别主要有以下几点:

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

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

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

总的来说,乐观锁适用于并发冲突较少的场景,可以提高系统的并发性;悲观锁适用于并发冲突较多的场景,可以保证数据的一致性和安全性。

1.3.综合案例

使用数据版本(Version)记录机制实现乐观锁,这是乐观锁最常用的一种实现方式。

  • 如何实现乐观锁?

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

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

2)更新时,带上这个 version

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

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

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

第一步:给数据库表添加 version 字段,并设置默认值为1

第二步:实体类增加 version 属性,并添加 @Version 注解

@Getter
@Setter
@TableName("t_book")
public class Book implements Serializable {
​
    private static final long serialVersionUID = 1L;
    
    /**
     * 书本类型
     */
    @TableField("booktype")
    private String booktype;
​
    /**
     * 乐观锁
     */
    @Version
    private Integer version;
}

第三步:配置乐观锁插件

@Configuration
public class MyBatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        //注册乐观锁插件
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return mybatisPlusInterceptor;
    }
}

第四步:测试

@Test
public void demo2(){
    //先查询,再修改
    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);//更新失败
}

2.逻辑删除

2.1.什么是逻辑删除

MyBatis-Plus中的逻辑删除(Logical Delete)是在数据库中进行虚拟删除,即实际删除数据时,并不会将数据从数据库中删除,而是通过一个标记来记录其已被删除。这种删除方式称为逻辑删除或软删除。

2.2.为什么使用逻辑删除

当我们使用物理删除时,数据将被永久删除,无法恢复。但有些情况下,我们并不希望永久删除数据,比如用户误删除、操作失误等情况,这时逻辑删除就尤为重要。

另外,逻辑删除还可以对应业务层逻辑,将数据状态标志为“已删除”,便于后续查询和统计。同时,逻辑删除还能提高删除操作效率,减少物理删除数据对系统性能的影响。

2.3.综合案例

2.3.1.官方提示

说明:只对自动注入的 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()

附录:

  • 逻辑删除是为了方便数据恢复和保护数据本身价值等等的一种方案,但实际就是删除。

  • 如果你需要频繁查出来看就不应使用逻辑删除,而是以一个状态去表示。

2.3.2.配置方式

  • 全局配置:

application.yml中添加全局逻辑删除配置,如下:

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: deleted # 全局逻辑删除的实体字段名
      logic-delete-value: 1       # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0   # 逻辑未删除值(默认为 0)

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

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

这里不需要配置@TableLogic注解,必须指定@TableField并设置对应数据库中的字段名。

  • 局部配置:

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

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

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

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

2.3.3.案例演示

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

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

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

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

3.分页和查询构造器

3.1.查询构造器

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

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

3.2.分页

  • 配置分页插件

@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/330624.html

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

相关文章

YOLOv5改进 | 检测头篇 | 利用DynamicHead增加辅助检测头进行针对性检测(让小目标无所遁形)

一、本文介绍 本文给大家带来的改进机制是针对性的改进,针对于小目标检测增加P2层,利用DynamicHead(原版本一比一复现,全网独一份,不同于网上魔改版本)进行检测,其中我们增加P2层其拥有更高的分辨率,这使得模型能够更好地捕捉到小尺寸目标的细节。在这些的基础上配合Dyn…

一、Flask学习之HTML

一、Flask学习之HTML 1.运行简单页面 首先需要搭建环境&#xff1a; pip install flaskfrom flask import Flaskapp Flask(__name__)# 创建了网址 /show/info 和函数index之间的对应关系&#xff0c;以后用户在浏览器上访问/show/info&#xff0c;网站自动执行index函数 ap…

npm超详细安装(包括配置环境变量)!!!npm安装教程(node.js安装教程)

安装node.js:(建议选择相对低一点的版本&#xff0c;相对稳定)​下载完成直接点击next即可(安装过程中会直接添加path的系统变量&#xff0c;变量值是自己的安装路径&#xff0c;可自行选择&#xff0c;比如&#xff1a;D:\software\)​安装完成:winR打开电脑控制台&#xff0c…

python依赖安装、执行、打包

python依赖安装、执行、编译打包 本文介绍python项目的依赖安装、执行、以及使用pyinstaller编译打包成可执行文件的命令。 python项目执行部署有两种方式&#xff0c;具体步骤&#xff1a; 一、python环境安装 --> 安装pip --> 依赖包安装 --> 执行python程序 二、使…

操作系统课程设计-Linux 进程间通信

目录 前言 1 实验题目 2 实验目的 3 实验内容 3.1 步骤 3.2 关键代码 3.2.1 Server和Client的创建 3.2.2 Server核心代码 3.2.3 Server核心代码 4 实验结果与分析 5 代码 前言 本实验为课设内容&#xff0c;博客内容为部分报告内容&#xff0c;仅为大家提供参考&…

如何在CentOS下使用Docker部署Halo博客网站并结合内网穿透远程访问

文章目录 ⛳️ 推荐1. Docker部署Halo1.1 检查Docker版本如果未安装Docker可参考已安装Docker步骤&#xff1a;1.2 在Docker中部署Halo 2. Linux安装Cpolar2.1 打开服务器防火墙2.2 安装cpolar内网穿透 3. 配置Halo个人博客公网地址4. 固定Halo公网地址 ⛳️ 推荐 前些天发现了…

关于LIN总线,同步间隔段最大时间及各种间隔符最大时间的解释,与说明

1&#xff1a;LIN同步间隔段的最小长度 如果问&#xff01;LIN同步间隔段的最小长度&#xff1f;大多数同学会一口答出">13bit位的显性位" 那如果问&#xff01;最大长度是多少&#xff1f; 则很少有同学会会突然懵逼&#xff01; 资料上给出的答案&#xff0…

2024杭州国际智慧城市,人工智能,安防展览会(杭州智博会)

在智能化浪潮的冲击下&#xff0c;我们的生活与环境正在经历一场深刻的变革。这是一场前所未有的技术革命&#xff0c;它以前所未有的速度和广度&#xff0c;改变着我们的生活方式、工作方式、思维方式和社会结构。在这场变革中&#xff0c;有的人选择激流勇进&#xff0c;拥抱…

JDBC概述和使用详解

文章目录 JDBC如何使用JDBC?Java 操作 数据库 JDBC 概述&#xff1a;Java Database Connectivity , Java数据库连接&#xff0c;通过Java语言操作数据库JDBC本质&#xff1a;官方定义的一套操作所有关系型数据库的规则&#xff0c;即接口。 各个数据库厂商去实现这套接口&…

pl/sql程序块的使用

-- Created on 2024-01-15 by ADMINISTRATOR declare -- Local variables hererecord_tablename varchar2(100);---test_record表名record_StartNo integer(19);---test_record开始编号temp_No integer(19);maxnbbh integer(19);nCnt integer : 20;fi…

安卓开发-day

一、安卓项目结构 1、manifests文件夹 Android系统配置文件夹&#xff0c;包含一个AndroidManifest.xml文件&#xff1b; AndroidMainifest.xml文件是每个android项目必须要包含的文件&#xff08;项目唯一&#xff09;&#xff0c;创建项目时默认就会生成这个文件&#xff0…

RDMA Send Receive操作详解

1. 前言 RDMA指的是远程直接内存访问&#xff0c;这是一种通过网络在两个应用程序之间搬运缓冲区里的数据的方法。RDMA与传统的网络接口不同&#xff0c;因为它绕过了操作系统。这允许实现了RDMA的程序具有如下特点&#xff1a; 绝对的最低时延 最高的吞吐量 最小的CPU足迹 &a…

人工智能 AI 如何让我们的生活更加便利

每个人都可以从新技术中获益&#xff0c;一想到工作或生活更为便利、简捷且拥有更多空余时间&#xff0c;谁会不为之高兴呢&#xff1f;借助人工智能&#xff0c;每天能够多一些空余时间&#xff0c;或丰富自己的业余生活&#xff0c;为培养日常兴趣爱好增添一点便利。从电子阅…

ubuntu18.04 安装mysql(命令)

1.安装MySQL #命令1 sudo apt-get update #命令2 sudo apt-get install mysql-server 2.配置MySQL sudo mysql_secure_installation 2.2 检查mysql服务状态 systemctl status mysql.service 3.配置远程访问 在Ubuntu下MySQL缺省是只允许本地访问的 3.1 首先用根用户进入…

CentOS安装maxwell

CentOs安装maxwell 一、简介二、准备工作三、安装1、下载安装包2、解压3、编写配置文件4、启动maxwell5、验证6、停止maxwell 四、说明1、更新数据2、插入数据3、删除数据 五、遇到问题 一、简介 maxwell是由美国Zendesk公司开源&#xff0c;它通过读取mysql的binlog日志&#…

大语言模型系列-Transformer

文章目录 前言一、Attention二、Transformer结构三、Transformer计算过程1. 编码器&#xff08;Encoder&#xff09;1&#xff09;Self-Attention层2&#xff09;Multi-Head-Attention层3&#xff09;Add & Norm层 2. 解码器&#xff08;Decoder&#xff09;1&#xff09;M…

CC工具箱使用指南:【坡度细碎图斑融合】

一、简介 这算是一个定制的工具&#xff0c;可惜没用上&#xff0c;扔掉也可惜&#xff0c;就放出来&#xff0c;可能会有同样需求的人用得上。 在ArcGIS中通过DEM生成的坡度是栅格格式的&#xff0c;再经过栅格转矢量后&#xff0c;会存在一些碎图斑。 这个工具的目的是&am…

从零开始学习Zeppelin:大数据可视化分析的交互式开发系统!

介绍&#xff1a;Apache Zeppelin是一个基于Web的交互式开发系统&#xff0c;主要用于进行大数据可视化分析。其核心概念是notebook&#xff0c;所有的操作都可以在notebook中完成。Zeppelin提供了一套非常全面的数据分析解决方案&#xff0c;支持数据采集、数据发现、数据分析…

7. UE5 RPG修改GAS的Attribute的值

前面几节文章介绍了如何在角色身上添加AbilitySystemComponent和AttributeSet。并且还实现了给AttributeSet添加自定义属性。接下来&#xff0c;实现一下如何去修改角色身上的Attribute的值。 实现拾取药瓶回血功能 首先创建一个继承于Actor的c类&#xff0c;actor是可以放置到…

力扣精选算法100题——四数之和(双指针专题)

上一篇讲到&#xff08;俩数之和and三数之和&#xff09;这一篇我要来解析四数之和&#xff0c;四数之和建立在三数之和的基础上&#xff0c;我们需要熟练掌握三数之和的算法原理&#xff0c;如果大家三数之和还没弄清楚&#xff0c;请点击三数之和and二数之和链接即可看到。 三…