Mybatis Plus乐观锁实现

2024-08-27 23:44
文章标签 实现 mybatis plus 乐观

本文主要是介绍Mybatis Plus乐观锁实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1 引言

乐观锁的主要作用在于提高系统的并发性能和减少锁冲突,同时保证数据的一致性。‌其原理简单来说就是,在修改数据的时候,判断数据是否被其他人改过,如果已被其他人改过,则修改失败。

2 代码

在SpringBoot 3.x+Mybatis Plus多数据源极简配置中的项目基础上更新代码,下面列出需要更新的代码。
在这里插入图片描述

2.1 org/example/mapper/InventoryMapperMaster.java

package org.example.mapper;import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.example.entity.Inventory;@DS("master")
public interface InventoryMapperMaster extends BaseMapper<Inventory> {}

2.2 org/example/entity/Inventory.java

@Version就是乐观锁字段,用于判断数据是否被修改过。

package org.example.entity;import com.baomidou.mybatisplus.annotation.*;import java.util.Date;/** 库存* */
@TableName("t_inventory")
public class Inventory {@TableId(type = IdType.AUTO)private Long id;private String name;private Integer quantity;@Version@TableField(fill = FieldFill.INSERT)private Integer version;@TableField(fill = FieldFill.INSERT)private Date createTime;@TableField(fill = FieldFill.INSERT_UPDATE)private Date updateTime;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getQuantity() {return quantity;}public void setQuantity(Integer quantity) {this.quantity = quantity;}public Integer getVersion() {return version;}public void setVersion(Integer version) {this.version = version;}public Date getCreateTime() {return createTime;}public void setCreateTime(Date createTime) {this.createTime = createTime;}public Date getUpdateTime() {return updateTime;}public void setUpdateTime(Date updateTime) {this.updateTime = updateTime;}
}

2.3 org/example/controller/InventoryController.java

package org.example.controller;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.example.entity.Inventory;
import org.example.entity.User;
import org.example.mapper.InventoryMapperMaster;
import org.example.mapper.UserMapperMaster;
import org.example.mapper.UserMapperSlave;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;@Controller
@RequestMapping("/InventoryController")
public class InventoryController {@Autowiredprivate InventoryMapperMaster inventoryMapperMaster;@RequestMapping(value = "/insert")@ResponseBody@Transactionalpublic Object insertMaster() {for (int i = 0; i < 5; i++) {Inventory inventory = new Inventory();inventory.setName("商品" + i);inventory.setQuantity(10);inventoryMapperMaster.insert(inventory);}return "数据插入成功";}@RequestMapping(value = "/update1")@ResponseBody@Transactionalpublic Object update1() {QueryWrapper<Inventory> q = new QueryWrapper<>();q.eq("name", "商品1");Inventory inventory = inventoryMapperMaster.selectOne(q);inventory.setQuantity(5);try {Thread.sleep(10000L);} catch (InterruptedException e) {throw new RuntimeException(e);}int i = inventoryMapperMaster.updateById(inventory);System.out.println("update1更新:" + i + "条");return "数据修改成功";}@RequestMapping(value = "/update2")@ResponseBody@Transactionalpublic Object update2() {QueryWrapper<Inventory> q = new QueryWrapper<>();q.eq("name", "商品1");Inventory inventory = inventoryMapperMaster.selectOne(q);inventory.setQuantity(0);int i = inventoryMapperMaster.updateById(inventory);System.out.println("update2更新:" + i + "条");return "数据修改成功";}}

2.4 org/example/conf/MyMetaObjectHandler.java

package org.example.conf;import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;import java.util.Date;/*MyBatis-Plus 提供了一个便捷的自动填充功能,用于在插入或更新数据时自动填充某些字段,如创建时间、更新时间等*/
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {this.setFieldValByName("createTime", new Date(), metaObject);this.setFieldValByName("updateTime", new Date(), metaObject);this.setFieldValByName("version", Integer.valueOf("0"), metaObject);}@Overridepublic void updateFill(MetaObject metaObject) {this.setFieldValByName("updateTime", new Date(), metaObject);}
}

2.5 org/example/conf/MybatisPlusConfig.java

package org.example.conf;import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*MyBatis-Plus 配置*/
@Configuration
public class MybatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();//添加分页拦截器interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));//添加乐观锁拦截器interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return interceptor;}}

3 测试

3.1 创建库存表

CREATE TABLE `t_inventory` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',`name` varchar(30) DEFAULT NULL COMMENT '名称',`quantity` int(11) DEFAULT NULL COMMENT '数量',`create_time` datetime DEFAULT NULL COMMENT '创建时间',`update_time` datetime DEFAULT NULL COMMENT '修改时间',`version` int(11) DEFAULT NULL COMMENT '版本',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

3.2 新增数据

启动项目,然后打开浏览器访问:http://localhost:8080/InventoryController/insert,可以看到当前所有商品的库存数量都是10个。
在这里插入图片描述

3.3 修改数据

  1. 我们以“商品1”为例,先访问http://localhost:8080/InventoryController/update1,将“商品1”的数量改为5。然后立即(10秒内)访问:http://localhost:8080/InventoryController/update2,将“商品1”的数量改为0。为了模拟并发的情况,这里让update1休眠了10秒钟再提交。
    在这里插入图片描述
  2. 可以看到sql中自动加入了version=0的条件,这个version就是乐观锁,由系统自动维护,每次成功修改数据自动+1。具体流程是:
    2.1 update1 首先查询商品1,这时quantity=10,version=0,查完进入休眠。
    2.2 update2 在update1 休眠期间,将商品1的数量改为0,这时version自动+1,变成quantity=0,version=1。
    2.3 update1 休眠结束后提交更新,仍然按照version=0的条件更新数据,此时version=0的数据已经不存在了,因此可以看到update1更新了0条数据,避免了数据不一致的情况。
    在这里插入图片描述

5 完整代码

Gitee代码链接

这篇关于Mybatis Plus乐观锁实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1113122

相关文章

mybatis的整体架构

mybatis的整体架构分为三层: 1.基础支持层 该层包括:数据源模块、事务管理模块、缓存模块、Binding模块、反射模块、类型转换模块、日志模块、资源加载模块、解析器模块 2.核心处理层 该层包括:配置解析、参数映射、SQL解析、SQL执行、结果集映射、插件 3.接口层 该层包括:SqlSession 基础支持层 该层保护mybatis的基础模块,它们为核心处理层提供了良好的支撑。

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略 1. 特权模式限制2. 宿主机资源隔离3. 用户和组管理4. 权限提升控制5. SELinux配置 💖The Begin💖点点关注,收藏不迷路💖 Kubernetes的PodSecurityPolicy(PSP)是一个关键的安全特性,它在Pod创建之前实施安全策略,确保P

工厂ERP管理系统实现源码(JAVA)

工厂进销存管理系统是一个集采购管理、仓库管理、生产管理和销售管理于一体的综合解决方案。该系统旨在帮助企业优化流程、提高效率、降低成本,并实时掌握各环节的运营状况。 在采购管理方面,系统能够处理采购订单、供应商管理和采购入库等流程,确保采购过程的透明和高效。仓库管理方面,实现库存的精准管理,包括入库、出库、盘点等操作,确保库存数据的准确性和实时性。 生产管理模块则涵盖了生产计划制定、物料需求计划、