mybitsPlus乐观锁@Version案例测试,发现有失效的情况

news2024/12/27 1:32:38

mybitsPlus乐观锁@Version案例测试,发现有失效的情况

一、案例


("NEWTABLE_TEST")
(value = "BusBalance对象", description = "额度表")
public class NewTableTest {
    private static final long serialVersionUID = 1L;

    (value = "ID")
    private String id;

    
    private Integer version;

    private String remark;

}

1、写入一条数据进行测试,此时版本号号为0。

String id = "1";
NewTableTest newTableTest = new NewTableTest();
newTableTest.setId(id);
newTableTest.setVersion(0);
newTableTest.setRemark("入库第一次");
testMapper.insert(newTableTest);

NewTableTest newTableTest1 = testMapper.selectById(id);
System.out.println("入库第一次:"+newTableTest1);
//入库第一次:NewTableTest(id=1, version=0, remark=入库第一次)

2、不设置version字段测试,更新成功,写入后版本号为1。

newTableTest.setRemark("修改第一次");
int i1 = testMapper.updateById(newTableTest1);
// Preparing: UPDATE NEWTABLE_TEST SET version=?, remark=? WHERE ID=? AND version=?
// Parameters: 1(Integer), 修改第一次(String), 1(String), 0(Integer)
System.out.println("修改第一次不设置version成功/失败:"+ (i1 == 0 ? false: true));
//修改第一次不设置version成功/失败:true
NewTableTest newTableTest2 = testMapper.selectById(id);
System.out.println("修改第一次不设置version:"+newTableTest2);
//修改第一次不设置version:NewTableTest(id=1, version=1, remark=修改第一次)

在这里插入图片描述

3、查询出的实体数据版本号+1=2进行测试,更新失败,版本号为1。

newTableTest2.setVersion(newTableTest2.getVersion() + 1);
newTableTest2.setRemark("修改第2次");
int i2 = testMapper.updateById(newTableTest2);
// ==>  Preparing: UPDATE NEWTABLE_TEST SET version=?, remark=? WHERE ID=? AND version=?
//==> Parameters: 3(Integer), 修改第2次(String), 1(String), 2(Integer)
System.out.println("修改第2次设置version+1成功/失败:"+ (i2 == 0 ? false: true));
//修改第2次设置version成功/失败:false
NewTableTest newTableTest3 = testMapper.selectById(id);
System.out.println("修改第2次设置version+1:"+newTableTest3);
//修改第2次设置version+1:NewTableTest(id=1, version=1, remark=修改第一次)

在这里插入图片描述

4、查询出的实体数据版本号随意写入数字进行测试,更新失败,版本号为1。

newTableTest3.setVersion(9);
newTableTest3.setRemark("修改第3次");
int i3 = testMapper.updateById(newTableTest3);
//==>  Preparing: UPDATE NEWTABLE_TEST SET version=?, remark=? WHERE ID=? AND version=?
//==> Parameters: 10(Integer), 修改第3次(String), 1(String), 9(Integer)
System.out.println("修改第3次设置version成功/失败:"+ (i3 == 0 ? false: true));
//修改第3次设置version成功/失败:false
NewTableTest newTableTest4 = testMapper.selectById(id);
System.out.println("修改第3次设置version:"+newTableTest4);
//修改第3次设置version:NewTableTest(id=1, version=1, remark=修改第一次)

在这里插入图片描述

5、使用update进行更新,实体为null,注解失效,更新成功(乐观锁需手动设置),版本号为9。

LambdaUpdateWrapper<NewTableTest> set = new LambdaUpdateWrapper<NewTableTest>()
                .eq(NewTableTest::getVersion, newTableTest4.getVersion())
                .eq(NewTableTest::getId, id)
                .set(NewTableTest::getVersion,9)
                .set(NewTableTest::getRemark,"测试");
        int update = testMapper.update(null, set);
        System.out.println("测试成功/失败:"+ (update == 0 ? false: true));
        //测试成功/失败:true
        NewTableTest newTableTest5 = testMapper.selectById(id);
        System.out.println("测试:"+newTableTest5);
        //测试:NewTableTest(id=1, version=9, remark=测试)

在这里插入图片描述

6、使用update进行更新,实体为不为null,注解生效,更新失败,版本号为9。

LambdaUpdateWrapper<NewTableTest> set2 = new LambdaUpdateWrapper<NewTableTest>()
                .eq(NewTableTest::getVersion, newTableTest5.getVersion())
                .eq(NewTableTest::getId, id);
newTableTest5.setVersion(20);
newTableTest5.setRemark("更新实体测试");
int update1 = testMapper.update(newTableTest5, set2);
System.out.println("更新实体测试成功/失败:"+ (update1 == 0 ? false: true));

//更新实体测试成功/失败:false

在这里插入图片描述

上面代码发现version条件再次多了一个,可能是注解生效了,把设置版本号代码注释掉。

LambdaUpdateWrapper<NewTableTest> set2 = new LambdaUpdateWrapper<NewTableTest>()
//                .eq(NewTableTest::getVersion, newTableTest5.getVersion())
                .eq(NewTableTest::getId, id);
newTableTest5.setVersion(20);
newTableTest5.setRemark("更新实体测试");
int update1 = testMapper.update(newTableTest5, set2);
System.out.println("更新实体测试成功/失败:"+ (update1 == 0 ? false: true));
更新实体测试成功/失败:false
NewTableTest newTableTest6 = testMapper.selectById(id);
System.out.println("更新实体测试:"+newTableTest6);
更新实体测试:NewTableTest(id=1, version=9, remark=测试)

注解生效,并且和上面一直,在设置的实体版本号+1进行更新。
在这里插入图片描述

7、实体为new出的实体,不设置任何值。注解失效,更新成功(乐观锁需手动设置),版本号更新为11。

LambdaUpdateWrapper<NewTableTest> set22 = new LambdaUpdateWrapper<NewTableTest>()
                .eq(NewTableTest::getVersion, newTableTest6.getVersion())
                .eq(NewTableTest::getId, id)
                .set(NewTableTest::getVersion,11)
                .set(NewTableTest::getRemark,"实体不设值测试");
int update2 = testMapper.update(new NewTableTest(), set22);
//Preparing: UPDATE NEWTABLE_TEST SET version=?,remark=? WHERE (version = ? AND ID = ?)
// ==> Parameters: 11(Integer), 实体不设值测试(String), 9(Integer), 1(String)
System.out.println("实体不设值测试成功/失败:"+ (update2 == 0 ? false: true));
//更新实体测试成功/失败:true
NewTableTest newTableTest55 = testMapper.selectById(id);
System.out.println("实体不设值测试成功:"+newTableTest55);
//实体不设值测试成功:NewTableTest(id=1, version=11, remark=实体不设值测试)

在这里插入图片描述

二、综上总结

1、mybitsPlus乐观锁@Version根据实体查询或者设置的值进行+1为set的值,实体版本号的值(查询出或者被重设)为会被默认为条件查询值。
所以实体设置乐观锁注解的值,查询出的该值,不能变更为其他值,否则会导致更新失败。

/**
 * newTableTest3.setVersion(9);
 * newTableTest3.setRemark("修改第3次");
 * int i3 = testMapper.updateById(newTableTest3);
 * Preparing: UPDATE NEWTABLE_TEST SET version=?, remark=? WHERE ID=? AND version=?
 * Parameters: 10(Integer), 修改第3次(String), 1(String), 9(Integer)
 */
//实体设置的值为9,sql则使用该值当条件。当前值+1为set的值。

2、@Version注解会有失效的情况。
使用updateById注解不会失效。
使用update如果实体为null,或者不赋值会导致注解失效。

3、尽量避免使用@Version注解,自行控制版本号。如果注解生效,但是又手动控制版本号会导致更新失败,不注意会导致数据问题。

三、测试demo


("NEWTABLE_TEST")
(value = "BusBalance对象", description = "额度表")
public class NewTableTest {
    private static final long serialVersionUID = 1L;

    (value = "ID")
    private String id;

    
    private Integer version;

    private String remark;

}
package com.ynyc.business.controller;


("api/test")
public class TestController {

    
    private NewTableTestMapper testMapper;

    ("index")
    public R<Object> index() {
        String id = "1";
        NewTableTest newTableTest = new NewTableTest();
        newTableTest.setId(id);
        newTableTest.setVersion(0);
        newTableTest.setRemark("入库第一次");
        testMapper.insert(newTableTest);

        NewTableTest newTableTest1 = testMapper.selectById(id);
        System.out.println("入库第一次:"+newTableTest1);
        //入库第一次:NewTableTest(id=1, version=0, remark=入库第一次)


        newTableTest.setRemark("修改第一次");
        int i1 = testMapper.updateById(newTableTest1);
        // Preparing: UPDATE NEWTABLE_TEST SET version=?, remark=? WHERE ID=? AND version=?
        // Parameters: 1(Integer), 修改第一次(String), 1(String), 0(Integer)
        System.out.println("修改第一次不设置version成功/失败:"+ (i1 == 0 ? false: true));
        //修改第一次不设置version成功/失败:true
        NewTableTest newTableTest2 = testMapper.selectById(id);
        System.out.println("修改第一次不设置version:"+newTableTest2);
        //修改第一次不设置version:NewTableTest(id=1, version=1, remark=修改第一次)


        newTableTest2.setVersion(newTableTest2.getVersion() + 1);
        newTableTest2.setRemark("修改第2次");
        int i2 = testMapper.updateById(newTableTest2);
        // ==>  Preparing: UPDATE NEWTABLE_TEST SET version=?, remark=? WHERE ID=? AND version=?
        //==> Parameters: 3(Integer), 修改第2次(String), 1(String), 2(Integer)
        System.out.println("修改第2次设置version+1成功/失败:"+ (i2 == 0 ? false: true));
        //修改第2次设置version成功/失败:false
        NewTableTest newTableTest3 = testMapper.selectById(id);
        System.out.println("修改第2次设置version+1:"+newTableTest3);
        //修改第2次设置version+1:NewTableTest(id=1, version=1, remark=修改第一次)




        newTableTest3.setVersion(9);
        newTableTest3.setRemark("修改第3次");
        int i3 = testMapper.updateById(newTableTest3);
        //==>  Preparing: UPDATE NEWTABLE_TEST SET version=?, remark=? WHERE ID=? AND version=?
        //==> Parameters: 10(Integer), 修改第3次(String), 1(String), 9(Integer)
        System.out.println("修改第3次设置version成功/失败:"+ (i3 == 0 ? false: true));
        //修改第3次设置version成功/失败:false
        NewTableTest newTableTest4 = testMapper.selectById(id);
        System.out.println("修改第3次设置version:"+newTableTest4);
        //修改第3次设置version:NewTableTest(id=1, version=1, remark=修改第一次)


        LambdaUpdateWrapper<NewTableTest> set = new LambdaUpdateWrapper<NewTableTest>()
                .eq(NewTableTest::getVersion, newTableTest4.getVersion())
                .eq(NewTableTest::getId, id)
                .set(NewTableTest::getVersion,9)
                .set(NewTableTest::getRemark,"测试");
        int update = testMapper.update(null, set);
        System.out.println("测试成功/失败:"+ (update == 0 ? false: true));
        //更新实体测试成功/失败:false
        NewTableTest newTableTest5 = testMapper.selectById(id);
        System.out.println("测试:"+newTableTest5);
        //更新实体测试:NewTableTest(id=1, version=9, remark=测试)




        LambdaUpdateWrapper<NewTableTest> set2 = new LambdaUpdateWrapper<NewTableTest>()
//                .eq(NewTableTest::getVersion, newTableTest5.getVersion())
                .eq(NewTableTest::getId, id);
        newTableTest5.setVersion(20);
        newTableTest5.setRemark("更新实体测试");
        int update1 = testMapper.update(newTableTest5, set2);
        System.out.println("更新实体测试成功/失败:"+ (update1 == 0 ? false: true));
        //测试成功/失败:true
        NewTableTest newTableTest6 = testMapper.selectById(id);
        System.out.println("更新实体测试:"+newTableTest6);




        LambdaUpdateWrapper<NewTableTest> set22 = new LambdaUpdateWrapper<NewTableTest>()
                .eq(NewTableTest::getVersion, newTableTest6.getVersion())
                .eq(NewTableTest::getId, id)
                .set(NewTableTest::getVersion,11)
                .set(NewTableTest::getRemark,"实体不设值测试");
        int update2 = testMapper.update(new NewTableTest(), set22);
        //Preparing: UPDATE NEWTABLE_TEST SET version=?,remark=? WHERE (version = ? AND ID = ?)
        // ==> Parameters: 11(Integer), 实体不设值测试(String), 9(Integer), 1(String)
        System.out.println("实体不设值测试成功/失败:"+ (update2 == 0 ? false: true));
        //更新实体测试成功/失败:true
        NewTableTest newTableTest55 = testMapper.selectById(id);
        System.out.println("实体不设值测试成功:"+newTableTest55);
        //实体不设值测试成功:NewTableTest(id=1, version=11, remark=实体不设值测试)


        //根据实体设置的值+1为set的值,实体设置的值为会被默认为当前查询出的值。
        /**
         * newTableTest3.setVersion(9);
         * newTableTest3.setRemark("修改第3次");
         * int i3 = testMapper.updateById(newTableTest3);
         * Preparing: UPDATE NEWTABLE_TEST SET version=?, remark=? WHERE ID=? AND version=?
         * Parameters: 10(Integer), 修改第3次(String), 1(String), 9(Integer)
         */
        //实体设置的值为9,sql则使用该值当条件。当前值+1为set的值。
        //所以实体设置乐观锁注解的值,查询出的该值,不能变更为其他值,否则会导致更新失败。

        return R.ok();
    }
}

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

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

相关文章

Servlet中的请求与响应

Request和Response 1.Request和Response的概述2.Request对象2.1 Request继承体系2.2 Request获取请求数据2.3 解决post请求乱码问题 *2.4 Request请求转发(-&#xff0c;*)2.5 request的生命周期 3.HTTP响应详解(理解)1.使用抓包查看响应报文协议内容2.HTTP响应报文协议介绍 4.…

[notice] A new release of pip is available: 23.2.1 -> 24.0

翻译之后&#xff1a;〔通知〕新版本的pip可用&#xff1a;23.2.1->24.0 就是说&#xff0c;你的pip版本需要从当前的 23.2.1 升级到最新版本 24.0&#xff0c;执行如下命令&#xff1a; cmd命令以管理员身份进入目录 ${Python}\Python3.12.1\Scripts下&#xff0c;执行 p…

分享金媒v10.3开源系统中CRM线下客户管理系统使用指南和小程序上架细分流程

本系统金媒婚恋开源系统v10.3也叫择爱系统目前最新版全开源包括OElove最新版10.0都是最新但是很多客户不动CRM使用流程我就按照流程给大家介绍下如果大家对程序感兴趣也可以分享给你看我昵称里可以Q我&#xff0c;请注明&#xff1a;CSDN网友 ●本系统红娘分两种&#xff0c;一…

杂题——1028: [编程入门]自定义函数求一元二次方程

题目描述 求方程 的根&#xff0c;用三个函数分别求当b^2-4ac大于0、等于0、和小于0时的根&#xff0c;并输出结果。从主函数输入a、b、c的值。 输入格式 a b c 输出格式 x1? x2? 样例输入 4 1 1 样例输出 x1-0.1250.484i x2-0.125-0.484i 分析&#xff1a; 注意输出的格式和…

论文阅读——SqueezeSAM

SqueezeSAM: User-Friendly Mobile Interactive Segmentation 比SAM更小&#xff0c;更快。 框架&#xff1a; 使用的U型结构 使用BatchNorm而不是LayerNorm节省计算&#xff1b; 对于用户点击和框&#xff0c;单独作为通道&#xff0c;前融合和后融合&#xff08;sam只有后融…

QML | 信号和信号处理器特性

信号和信号处理器特性 很多时候,应用程序的用户界面组件需要相互通信。例如,一个按钮需要知道用户是否进行了单击:当用户单击后,它可能会更改颜色来指示它状态的改变,或者执行一些逻辑代码实现一定的功能。同Qt一样,QML包含了相似的信号和信号处理器机制。 信号是发出事件…

惠尔顿安全审计系统任意文件读取漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

每日OJ题_二叉树dfs③_力扣814. 二叉树剪枝

目录 力扣814. 二叉树剪枝 解析代码 力扣814. 二叉树剪枝 814. 二叉树剪枝 难度 中等 给你二叉树的根结点 root &#xff0c;此外树的每个结点的值要么是 0 &#xff0c;要么是 1 。 返回移除了所有不包含 1 的子树的原二叉树。 节点 node 的子树为 node 本身加上所有 n…

读书笔记-增强型分析:AI驱动的数据分析、业务决策与案例实践

目录 前言 运用人工智能技术&#xff0c;可以使人类社会变得更美好。人们总是期待产品更适合、服务更贴心、生活更便利。在实践中&#xff0c;技术给企业赋能&#xff0c;企业通过优质的产品和服务满足社会&#xff0c;提升人类福祉。很多金融企业已经开始尝试向潜在客户推送…

使用JavaVisualVM排查FullGC问题

1.工具准备 在这里使用 jdk/bin 目录下的 jvisualvm.exe&#xff0c;是自带工具。 2.工具使用 将下载到本地的dump 文件导入工具中&#xff0c;会展示各个类的实例数占比&#xff0c;大小占比。 3.问题排查 前期准备 在分析dump文件之前&#xff0c;我们可以先观察应用中接…

01 前言

目录 什么是CC发展史C的重要性如何学习C关于本专栏 1. 什么是c C语言是结构化和模块化的语言&#xff0c;适合处理较小规模的程序。对于复杂的问题&#xff0c;规模较大的程序&#xff0c;需要高度的抽象和建模时&#xff0c;C语言则不合适。为了解决软件危机&#xff0c; 20…

一文了解大数据生态

大数据一词最早指的是传统数据处理应用软件无法处理的过于庞大或过于复杂的数据集。 现在&#xff0c;对“大数据”一词的使用倾向于使用预测分析、用户行为分析或者其他一些从大数据中提取价值的高级数据分析方法&#xff0c;很少用于表示特定规模的数据集。 定义 大数据是…

机器视觉系统选型-为什么还要选用工业光源控制器

工业光源控制器最主要的用途是给光源供电&#xff0c;实现光源的正常工作。 1.开关电源启动时&#xff0c;电压是具有波浪的不稳定电压&#xff0c;其瞬间峰值电压超过了LED灯的耐压值&#xff0c;灯珠在多次高压冲击下严重降低了使用寿命&#xff1b; 2.使用专用的光源控制器&…

Netty中的PooledByteBuf池化原理剖析

PooledByteBuf PooledByteBuf是池化的ByteBuf&#xff0c;提高了内存分配与释放的速度&#xff0c;它本身是一个抽象泛型类&#xff0c; 有三个子类:PooledDirectByteBuf、PooledHeapByteBuf、PooledUnsafeDirectByteBuf. Jemalloc算法 Netty的PooledByteBuf采用与jemalloc一…

SICTF Round#3 の WP

Misc 签到 SICTF{1f4ce05a-0fed-42dc-9510-6e76dff8ff53} Crypto [签到]Vigenere 附件内容&#xff1a; Gn taj xirly gf Fxgjuakd, oe igywnd mt tegbs mnrxxlrivywd sngearbsw wakksre. Bs kpimj gf tank, it bx gur bslenmngn th jfdetagur mt ceei yze Ugnled Lystel t…

NFC三大工作模式及其在物联网应用实例

NFC支持三种通信模式&#xff1a;读写模式、点对点模式和卡模拟模式。在此三种模式下&#xff0c;都仅需简单点击便可启动传输。 在读写模式下&#xff0c;系统执行非接触式读写功能。该系统的NFC芯片与内置NFC的设备-诸如非接触式智能卡、NFC标签或具有NFC功能的智能手机&…

pylint、pyreverse

文章目录 pylintpyreverse pylint github : https://github.com/pylint-dev/pylint官网&#xff1a;https://www.pylint.org文档&#xff1a;https://pylint.readthedocs.io/en/latest/ Pylint 是一个 Python 代码分析工具&#xff0c;它分析 Python 代码中的语法错误&#xf…

【代码随想录python笔记整理】第十二课 · 位置互换

前言:本笔记仅仅只是对内容的整理和自行消化,并不是完整内容,如有侵权,联系立删。 一、变量交换的实现 这节我们讨论一个简单的问题——怎么交换两个变量的值。比如说,一个瓶子里是水,一个瓶子里是油,想要将两个瓶子中的东西互换,我们应该怎么做呢?要实现上述过程,我们…

leetcode hot100 完全平方数

本题中&#xff0c;是给一个整数n&#xff0c;让用完全平方数凑出这个整数&#xff0c;注意&#xff0c;题中给了n的范围&#xff0c;是大于等于1的&#xff0c;也就是说&#xff0c;dp[0]我们可以先不考虑。 整个问题可以抽象成完全背包问题的变形形式&#xff0c;物品就是这…

免费听歌软件,音乐搜索APP:掌中的音乐宝库,为您的音乐生活增添色彩

引言 在数字音乐的浪潮中&#xff0c;我们通常会想到QQ音乐、虾米、网易云音乐等主流平台APP。然而&#xff0c;这些商业软件在为用户提供服务的同时&#xff0c;也不可避免地伴随着一些限制和不尽如人意的地方&#xff0c;如曲库有限、音质不尽如人意或广告干扰或会员才能听歌…