【MyBatis-Plus】逻辑删除、乐观锁、防全表更新和删除实现 MyBatisX插件 高级扩展


一、逻辑删除实现

  • 物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除的数据
  • 逻辑删除:假删除,将对应数据中代表是否被删除字段的状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录

逻辑删除实现:

  • 数据库 和 实体类 添加逻辑删除字段
    • 数据表添加逻辑删除字段
    • 可以是一个布尔类型、整数类型或枚举类型。
ALTER TABLE USER ADD deleted INT DEFAULT 0 ;  # int 类型 1 逻辑删除 0 未逻辑删除
  • 实体类添加逻辑删除属性
@Data
public class User {
    private Long id;
    @TableField(value = "nickname",exist = false)
    private String name;
    private Integer age;
    private String email;

    // 当前属性对应的列就是逻辑删除的状态字段
    // 当删除数据时,自动变成修改此列的属性值 默认0未删除 1删除
    // 查询时,默认只查询 deleted = 0 未删除的数据
    @TableLogic
    private Integer deleted;
}
  • 指定逻辑删除字段和属性值
    • 单一指定
      • 在实体类属性上创建属性 指定注解@TableLogic
    • 全局指定
      • yml 配置文件 添加 logic-delete-field
        1
        源码中默认值 就设置了未删除0 删除为1,可以保持默认即可。
        1
  • 测试:
    • 逻辑删除:不使用delete语句而是修改语句 update user set deleted=1 where id=#{id}
    • 物理删除:delete from user where id=#{id}
    @Test
    public void delete_test2(){
        userMapper.deleteById(2);
    }

Preparing: UPDATE user SET deleted=1 WHERE id=? AND deleted=0
1
正常查询 : 默认查询非逻辑删除数据

二、乐观锁实现

2.1 悲观锁和乐观锁场景和介绍

需求前置:并发问题演示
1
使用乐观锁/悲观锁解决:
乐观锁悲观锁是在并发编程中用于处理并发访问资源竞争的两种不同的机制

  • 悲观锁
    • 当A在使用时,上锁了,B尝试使用被拒绝,因为上锁了
    • 只能等A用完后,解锁了,B再次去尝试使用。
  • 乐观锁
    • 当A使用,不会上锁,B可以尝试使用,但被告知已被占用,不能用
    • 区别于悲观锁 -> 乐观锁的B会反复的尝试,直到A使用完毕
  • 这两者都是解决并发数据问题思路,不是具体技术

2.2 具体技术和方案:

乐观锁:

  • 版本号/时间戳
    • 为数据添加一个版本号或时间戳字段,每次更新数据时
    • 比较当前版本号或时间戳与期望值是否一致
    • 若一致则更新成功,否则表示数据已被修改,需要进行冲突处理。
  • CAS(Compare-and-Swap)
  • 无锁数据结构
    • 无锁队列、无锁哈希表等…

悲观锁:

  • 锁机制
    • 互斥锁(Mutex Lock)或读写锁(Read-Write Lock)
  • 数据库锁
    • 数据库层面使用行级锁或表级锁来控制并发访问
  • 信号量

2.3 版本号乐观锁技术的实现流程

  • 每条数据添加一个版本号字段version
  • 取出记录时,获取当前 version
  • 更新时,检查获取版本号是不是数据库当前最新版本号
  • 如果是[证明没有人修改数据], 执行更新, set 数据更新 , version = version+ 1
  • 如果 version 不对[证明有人已经修改了],我们现在的其他记录就是失效数据!就更新失败

2.4 使用mybatis-plus数据使用乐观锁

  • 添加版本号更新插件,在springboorMain类
    1
    /**
     * 将 mybatis-plus 插件加入到IOC容器
     * @return
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        //mybatis-plus的插件集合【将需要的插件加入到这个集合中即可,比如分页插件,乐观锁插件等】
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        //乐观锁【版本号插件】mybatis-plus 会在更新时,每次帮助我们对比版本号字段和增加版本号+1
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return mybatisPlusInterceptor;
    }
  • 数据库添加version字段
ALTER TABLE USER ADD VERSION INT DEFAULT 1 ;  # int 类型 乐观锁字段

1

  • 支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
  • 仅支持 updateById(id)update(entity, wrapper) 方法
  • 实体类添加version属性
    @Version
    private Integer version;
  • 测试 正常更新
    //演示乐观锁生效场景
    @Test
    public void testQuick7(){
        //步骤1: 先查询,在更新 获取version数据
        //同时查询两条,但是version唯一,最后更新的失败
        User user  = userMapper.selectById(5);
        User user1  = userMapper.selectById(5);

        user.setAge(20);
        user1.setAge(30);

        userMapper.updateById(user);
        //乐观锁生效,失败!
        userMapper.updateById(user1);
    }

先查再改:
1
1

三、防全表更新和删除实现

针对 update 和 delete 语句 作用: 阻止恶意的全表更新删除
在这里插入图片描述

  • 添加防止全表更新和删除拦截器
        // 防止全表删除和更新拦截器
        mybatisPlusInterceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());

1
### Cause: com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: Prohibition of table update operation

三、代码生成器(MyBatisX插件)

1
1

使用mybatisX插件,自动生成sql语句实现

MyBatisX快速代码生成_官方文档

  • 24
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

道格维克

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

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

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

打赏作者

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

抵扣说明:

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

余额充值