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

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

一、案例


("NEWTABLE_TEST")
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=测试)

注解生效,并且和上面2不设置version字段一致,在设置的实体版本号+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();
    }
}
  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

怪异的bug

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值