MyBatisPlus 之四:MP 的乐观锁和逻辑删除、分组、排序、链式的实现步骤

乐观锁

乐观锁是相对悲观锁而言的,乐观锁假设数据一般情况不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果冲突,则返回给用户异常信息,让用户决定如何去做。

乐观锁适用于读多写少的场景,这样可以提高程序的吞吐量。

乐观锁采取了更加宽松的加锁机制。也是为了避免数据库幻读、业务处理时间过长等原因引起数据处理错误的一种机制,但乐观锁不会刻意使用数据库本身的锁机制,而是依据数据本身来保证数据的正确性。

乐观锁的实现:

  1. CAS 实现:Java 中java.util.concurrent.atomic包下面的原子变量使用了乐观锁的一种 CAS 实现方式。
  2. 版本号控制:一般是在数据表中加上一个数据版本号 version 字段,表示数据被修改的次数。当数据被修改时,version 值会 +1。当线程 A 要更新数据时,在读取数据的同时也会读取 version 值,在提交更新时,若刚才读取到的 version 值与当前数据库中的 version 值相等时才更新,否则重试更新操作,直到更新成功。

2️⃣说明 乐观并发控制相信事务之间的数据竞争(data race)的概率是比较小的,因此尽可能直接做下去,直到提交的时候才去锁定,所以不会产生任何锁和死锁。

MP 中乐观锁的实现

官网描述

OptimisticLockerInnerInterceptor 是 MyBatis Plus 提供的一个内置拦截器,用于实现乐观锁机制。

在并发环境下,乐观锁可以有效防止因并发更新导致的数据不一致问题

当要更新一条记录的时候,希望这条记录没有被别人更新 乐观锁实现方式:

  • 取出记录时,获取当前version

  • 更新时,带上这个version

  • 执行更新时, set version = newVersion where version = oldVersion

  • 如果version不对,就更新失败

实现步骤:

a. 配置插件

package com.wdzl.config;import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;//Spring boot方式
@Configuration
public class MybatisPlusConfig {/*** 新版*/@Beanpublic MybatisPlusInterceptor mybatisPlusLockInterceptor() {MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();// OptimisticLockerInnerInterceptor 是 MyBatis Plus 提供的一个内置拦截器mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return mybatisPlusInterceptor;}
}

b. 修改表结构

增加一列,用来表示记录的版本。类型必须是数值型的

create table book(bookid int primary key,bookname varchar(200),price float,pubdate datetime,author varchar(20),version int  
);

说明:

  • 支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
  • 整数类型下 newVersion = oldVersion + 1
  • newVersion 会回写到 entity 中
  • 仅支持 updateById(id) 与 update(entity, wrapper) 方法
  • 在 update(entity, wrapper) 方法下, wrapper 不能复用!!!

c. 修改实体类

增加版本属性,并使用注解 @Vesion 标注。

注意:属性名命名没有要求。

@Version
private Integer version;

d. 测试

    /*** UPDATE book SET bookName=?, price=?, pubdate=?, author=?, version=? WHERE bookid=?             AND version=?*/@Testpublic void lock(){Book book = bookDao.selectById(22);book.setPrice(book.getPrice()-5);Book book2 = bookDao.selectById(22);book2.setPrice(book.getPrice()-60);bookDao.updateById(book); //按主键修改//修改失败bookDao.updateById(book2);}
}

注意:配置好乐观锁插件和实体类注解后,再次修改,发现 SQL 语句的变化。添加了对于 version 版本字段的添加和修改

UPDATE book SET bookName=?, price=?, pubdate=?, author=?, version=? WHERE bookid=? AND version=?

逻辑删除

逻辑删除是数据库管理中的一种策略,它并不真正从数据库物理层面删除数据,而是通过更新数据表中的某个字段来标记这条记录为“已删除”状态。这样做的好处是可以保留历史数据,避免因误删导致的数据丢失,并且在需要时可以查询到被逻辑删除的记录。

在 MyBatis Plus 中,逻辑删除功能已经内置并提供了便捷的实现方式

官网说明:

说明:

只对自动注入的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
实现步骤:

a) 修改表添加字段

表中添加一个列,用来表示删除状态的列

create table book(bookid int primary key,bookname varchar(200),price float,pubdate datetime,author varchar(20),version int,deleted int
);

b) 对应修改实体类,增加状态属性。

实体类字段上加上@TableLogic注解

@TableLogic
private Integer deleted;

c) 提前规定好删除标志的值和正常的值

可以在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)

d) 测试:

    @Testvoid logicdel(){//SELECT bookid,bookName,price,pubdate,author,version,state FROM book WHERE state=0
//        List<Book> list = bookDao.selectList(null);//删除时 UPDATE book SET state=1 WHERE bookid=? AND state=0bookDao.deleteById(27);}

注意:在做select 查询,update 修改,删除操作时,执行的 SQL 都会有所变化。结合version来操作

分组

实现要求:

-- 按作者分组,查询每个作者初版的书数量及平均价格
SELECT author, AVG(price) 平均价格,COUNT(*) 数量
FROM book
WHERE state=0
GROUP BY author
HAVING COUNT(*)>2

代码实现:

void group(){QueryWrapper<Book> queryWrapper = new QueryWrapper<>();queryWrapper.select("author","count(*) bookCount","avg(price) pavg").groupBy("author").having("count(*)>2");List<Map<String, Object>> maps = bookDao.selectMaps(queryWrapper);for (Map<String, Object> map : maps) {String author = (String)map.get("author");Long count  = (Long)map.get("bookCount");Double pavg = (Double)map.get("pavg");System.out.println(author+"==="+count+"==="+pavg);}
}

排序、或、链式编程

/*** order by*/public void order(){QueryWrapper<Book> queryWrapper = new QueryWrapper<>();
//        queryWrapper.orderByAsc("price");queryWrapper.orderByDesc("price").orderByAsc("pubDate").le("price",34).or().gt("pubDate",new Date()).and(t->t.notIn("bookid",34,45,56)) .gt("price",56);bookDao.selectList(queryWrapper);

 

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

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

相关文章

[Qt学习笔记]QT下获取Halcon图形窗口鼠标事件并执行相应操作

目录 1、背景2、参考信息3、目标4、步骤4.1 Halcon库的配置4.2 读取图像&#xff0c;并实现图像自适应窗体控件大小4.3 主要的图形绘制和贴图操作见如下代码&#xff0c;其中重点为全局函数的创建来实现选择Select、拖拽Drag和尺寸Resize事件响应。 5、总结 1、背景 在视觉项目…

3.19作业

1、思维导图 2、模拟面试题 1&#xff09;TCP通信中的三次握手和四次挥手 答&#xff1a;三次握手 客户端向服务器发送连接请求 服务器向客户端回复应答并向客户端发送连接请求 客户端回复服务端&#xff0c;并建立联系 四次挥手 进程a向进程b发送断开连接请求…

3.20作业

1、思维导图 2、 1> 创建一个工人信息库&#xff0c;包含工号&#xff08;主键&#xff09;、姓名、年龄、薪资。 2> 添加三条工人信息&#xff08;可以完整信息&#xff0c;也可以非完整信息&#xff09; 3> 修改某一个工人的薪资&#xff08;确定的一个&am…

踏“时间”与“空间”前来探寻复杂度的奥妙(Java篇)

本篇会加入个人的所谓‘鱼式疯言’ ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人…

校园综合能效平台建设的意义

彭姝麟 Acrelpsl 一 高校用能分析 当前高校用能普遍存在以下点问题&#xff1a; 一是用能需求日益增加&#xff1a;随着高校的快速发展&#xff0c;校园用能人数、用能设备、建筑面积等逐年增加&#xff0c;用能需求也相应攀升。日益增长的能耗需求与节能降耗任务之间的客观矛…

一文读懂什么是序列 (sequence)

sequence 序列 sequence(序列)是一组有顺序的元素的集合 (严格的说&#xff0c;是对象的集合&#xff0c;但鉴于我们还没有引入“对象”概念&#xff0c;暂时说元素) 序列可以包含一个或多个元素&#xff0c;也可以没有任何元素。 我们之前所说的基本数据类型&#xff0c;都…

蓝桥杯练习03个人博客

个人博客 介绍 很多人都有自己的博客&#xff0c;在博客上面用自己的方式去书写文章&#xff0c;用来记录生活&#xff0c;分享技术等。下面是蓝桥云课的博客&#xff0c;但是上面还缺少一些样式&#xff0c;需要大家去完善。 准备 开始答题前&#xff0c;需要先打开本题的…

物业社区人行通道闸如何选择,这6点一定要考虑!

社区是居民的共同家园&#xff0c;一个安全、便捷且和谐的社区环境对于提升居民的生活质量至关重要。人行通道闸不仅仅是一道简单的进出关卡&#xff0c;它是守护社区人员通行安全的坚实屏障&#xff0c;是提升社区管理效率的智能工具&#xff0c;更是增强业主满意度的关键因素…

C# 部署ICE框架以及用例(VS2019)

使用Windows 10环境&#xff0c;VS2019进行ICE用例开发 用例结构&#xff1a;客户端和服务端 关键技术&#xff1a;集成ICE环境&#xff0c;可以创建ice文件并自动生成对应的cs文件 1.环境安装 ICE Build插件安装。安装以后&#xff0c;就可以在项目中插入ice文件 2.代码实…

放大镜效果

放大镜效果 摘要 利用css和js来实现图片放大效果 HTML <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><titl…

Go——切片

1. 特点 slice并不是数组或数组指针。它通过内部指针和相关属性引用数组片段&#xff0c;以实现变长方案。 切片&#xff1a;切片是数组的一个引用&#xff0c;因此切片是引用类型。但自身是结构体&#xff0c;值拷贝传递。切片的长度可以改变&#xff0c;因此&#xff0c;切片…

Elasticsearch实战:索引阻塞 —— 数据保护的终极武器

文章目录 1、索引阻塞的种类2、什么时候使用阻塞&#xff1f;场景1&#xff1a;进行系统维护场景。场景2&#xff1a;保护数据不被随意更改场景。场景3&#xff1a;优化资源使用的场景。场景4&#xff1a;遵守安全规则场景。 3、添加索引阻塞API4、解除设置 API5、小结6、参考 …

Transformer位置编码(Position Embedding)理解

本文主要介绍4种位置编码&#xff0c;分别是NLP发源的transformer、ViT、Sw-Transformer、MAE的Position Embedding 一、NLP transformer 使用的是1d的绝对位置编码&#xff0c;使用sincos将每个token编码为一个向量【硬编码】 Attention Is All You Need 在语言中&#xff0…

RPG Maker MV 踩坑八 仿新仙剑战斗物品指令菜单

仿新仙剑战斗物品指令菜单 遇到的坑坑一坑二解决方法 遇到的坑 上次做的额外战斗指令菜单和物品战斗指令菜单&#xff0c;突然发现一个大问题&#xff0c;漏风了&#xff01;&#xff01;&#xff01; 其实就是将底部漏出来了&#xff0c;这样整个UI就不完整了&#xff0c;算是…

微服务day04(上)-- RabbitMQ学习与入门

1.初识MQ 1.1.同步和异步通讯 微服务间通讯有同步和异步两种方式&#xff1a; 同步通讯&#xff1a;就像打电话&#xff0c;需要实时响应。 异步通讯&#xff1a;就像发邮件&#xff0c;不需要马上回复。 两种方式各有优劣&#xff0c;打电话可以立即得到响应&#xff0c;但…

深度学习 | 神经网络

一、神经网络原理 1、神经元模型 虽然叫个神经元&#xff0c;但骨子里还是线性模型。 2、神经网络结构 顾名思义就是由很多个神经元结点前后相连组成的一个网络。虽然长相上是个网络&#xff0c;但是本质上是多个线性模型的模块化组合。 在早期也被称为 多层感知机 Multi-Layer…

Visual Studio 2013 - 调试模式下根据内存地址查看内存

Visual Studio 2013 - 调试模式下根据内存地址查看内存 1. 查看内存References 1. 查看内存 调试 -> 窗口 -> 内存 -> 内存1-4 References [1] Yongqiang Cheng, https://yongqiang.blog.csdn.net/

【质押空投】公链Zkasino

据深潮TechFlow报道&#xff0c;游戏公链Zkasino HyperChain宣布上线质押挖矿活动&#xff0c;参与者可通过将ETH跨链到Zkasino链的方式来获取ZKAS代币。本次活动总共将分配25%的总代币供应量给参与者。质押挖矿时间将通过倒计时的方式来限制参与人数&#xff0c;以保护早期质押…

Datawhale 零基础入门数据挖掘-Task1 赛题理解

一、 赛题理解 Tip:此部分为零基础入门数据挖掘的 Task1 赛题理解 部分&#xff0c;为大家入门数据挖掘比赛提供一个基本的赛题入门讲解&#xff0c;欢迎后续大家多多交流。 赛题&#xff1a;零基础入门数据挖掘 - 二手车交易价格预测 地址&#xff1a;零基础入门数据挖掘 -…

【代码分享】四十七种测试函数(关注可免费获取)

智能优化算法测试函数简介 智能优化算法测试函数是为了在优化算法研究和开发中测试算法性能的规范问题集合。这些测试函数模拟了真实世界优化问题的不同方面,包括局部最小值、最大值、全局最优解,以及多种复杂性如高维度、非线性、不连续等。优化算法,如遗传算法、粒子群优…