Mybatis Plus【3】——左手乐观锁、右手逻辑删除在数据层为所欲为

本文介绍了MyBatis-Plus中的乐观锁和逻辑删除功能。乐观锁用于在多线程环境下确保数据更新的安全,通过版本号机制实现。逻辑删除则提供了一种假删除的方式,避免真正删除数据。文章详细阐述了如何在数据库中添加相关字段,实体类中添加注解,配置元对象处理器,以及如何在应用中启用和测试这两个特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首次接触MyBatis-Plus是在2018年年年底,因MyBatis-Plus的强大功能,目前不少公司都会引入,也深深吸引了我,我公司技术选型时我也会引入了MyBatis-Plus,在使用【若依】等框架时也会将其中的mybatis替换为mybatis-plus进行重构,遂通过MyBatis专栏将MyBatis和MyBatis-Plus的相关技术点安利给读者朋友,喜欢的点个赞吧,非常实用!

系列文章目录

第一章 myBatis分页插件pageHelper
第二章 MyBatis-Plus【1】—— 基本使用
第三章 MyBatis-Plus【2】——解锁MyBatis这些功能代码少些3成
第四章 Mybatis-Plus【3】——左手乐观锁、右手逻辑删除在数据层为所欲为
第五章 Mybatis Plus【4】—— 条件构造器 体系结构和详细案例


一、乐观锁

乐观锁是用来解决多线程情况下同一条数据同时可能被多人一起修改,造成数据紊乱的一种解决方案,当更新一条数据时,希望这条数据没有被别人更新,也就是说实现线程安全的数据更新。

判断有没有被修改的策略就是在准备更新时获取该数据的版本,在更新时检查版本是否相同,更新后将数据的版本修改来实现。

对于乐观锁和悲观锁的详细介绍可以参考 什么是乐观锁,什么是悲观锁 文章

1.1、实现方式

在Mybatis Plus步骤如下

  • 取出记录时,获取当前version
  • 更新记录时,带上这个version
  • 执行更新时,set version = newVersion where version = oldVersion
  • 如果version不对,就更新失败

1.2、实现步骤

  • 在数据表中新增 version 字段,类型为int
  • 在实体类中新增 version 属性,并使用 @Version 注解修饰
  • 元数据处理接口添加 version 的 insert 默认值(可以不做,目的在于自动填充有个默认值而已)
  • 编写配置类,配置 乐观锁插件

1.3、数据库添加字段

基于 MyBatis-Plus【2】 也就是上篇文章的基础,在您自己的表中创建一个 version 字段,也可以按照下方sql实现:

ALTER TABLE `user` ADD COLUMN `version` INT

1.4、实体类

  • @Version:实现乐观锁注解
  • @TableField(fill = FieldFill.INSERT):实现自动填充,在新增数据时填充一个初始的版本号,当然您也可以设置数据库的默认值等方式
@Version
@TableField(fill = FieldFill.INSERT)
private Integer version;

1.5、元数据处理接口

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    // 使用MP实现添加操作,该方法执行
    @Override
    public void insertFill(MetaObject metaObject) {
        ......
        this.setFieldValByName("version",1,metaObject);
    }

    // 使用MP实现修改操作,该方法执行
    @Override
    public void updateFill(MetaObject metaObject) {
        ......
    }
}

1、支持的数据类型只有int、Integer、long、Long、Date、Timestamp、LocalDateTime
2、整数类型下 newVersion = oldVersion + 1
3、newVersion会写回到entity中
4、仅支持 updateById(id) 和 update(entity,warpper)方法
5、在update(entity,warpper)方法下,warpper不能重用

1.6、乐观锁配置类

@Configuration
@EnableTransactionManagement
@MapperScan(value = "com.buye.mp.mapper")
public class MyBatisPlusConfig {

    /**
     * 新版 插件配置方式
     * @return
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return mybatisPlusInterceptor;
    }

    /**
     * 旧版
     * @Bean
     * public OptimisticLockerInterceptor optimisticLockerInterceptor() {
     *    return new OptimisticLockerInterceptor();
     * }
     */
}

1.7、测试

首先新增一条数据,因为有自动填充version,所以它的version是1,然后再根据id修改

@Test
public void addUser() {
    // 创建User对象,并设置属性,此处没有设置id
    User user = new User();
    user.setName("不夜同学");
    user.setEmail("test10.@baomidou.com");
    user.setAge(14);
    // 调用insert函数将用户添加进数据库
    int row = userMapper.insert(user);
    System.out.println("成功新增" + row + "条数据");
}

@Test
public void testOptimisticLokker() {
    // 1、根据id查询数据
    User user = userMapper.selectById(1452181379893747714L);
	// 2、设置,修改数据
    user.setAge(18);

    userMapper.updateById(user);
}

效果图如下,默认version为1,修改后version为2

请添加图片描述

sql执行如下
请添加图片描述

二、逻辑删除

逻辑删除假删除,将对应数据中代表是否删除字段状态修改为 被删除状态,之后数据仍然存在与数据库中;

物理删除真实删除:将对应数据从数据库中删除,之后查询不到此条被删除数据;

2.1、实现步骤

  • 想数据库中添加 deleted 字段

  • 实体类中添加 deleted 字段

  • 元对象处理器接口添加 deleted 的 insert 默认值(可以不做,只是为了新增数据时有默认值)

  • application.properties 加入配置

  • 在配置类中配置Bean【mybatis plus高版本已经不需要配置了】

2.2、新增字段

ALTER TABLE `user` ADD COLUMN `deleted` boolean

2.3、实体类新增deleted字段

  • @TableLogic:实现逻辑删除注解
@TableLogic
@TableField(fill = FieldFill.INSERT)
private Integer deleted;

2.4、application配置文件

该配置可以不做,默认0未删除,1以删除

# 逻辑删除已删除值(默认为1)
mybatis-plus.global-config.db-config.logic-delete-value=1
# 逻辑删除未删除值(默认为0)
mybatis-plus.global-config.db-config.logic-not-delete-value=0

2.5、测试

2.5.1、新增数据

@Test
public void addUser() {
    // 创建User对象,并设置属性,此处没有设置id
    User user = new User();
    user.setName("不夜学长");
    user.setEmail("test11.@baomidou.com");
    user.setAge(14);
    // 调用insert函数将用户添加进数据库
    int row = userMapper.insert(user);
    System.out.println("成功新增" + row + "条数据");
}

新增数据的deleted默认值为0,这里我们并没有设置自动填充哦!
请添加图片描述

2.5.2、删除数据

@Test
public void testLogicDelete() {

    int row = userMapper.deleteById(1452267209106739202L);
    System.out.println(row);

}

测试结果

请添加图片描述

2.5.3、添加逻辑删除后的查询

配置逻辑删除下的查询自带上 deleted = 0 条件
请添加图片描述

2.6、注意

如果需要查询出被逻辑删除的数据,那么就需要自己写sql语句啦

只对自动注入的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

字段类型支持说明:

  • 支持所有数据类型(推荐使用 Integer,Boolean,LocalDateTime)
  • 如果数据库字段使用datetime,逻辑未删除值和已删除值支持配置为字符串null,另一个值支持配置为函数来获取值如now()

附录:

  • 逻辑删除是为了方便数据恢复和保护数据本身价值等等的一种方案,但实际就是删除。
  • 如果你需要频繁查出来看就不应使用逻辑删除,而是以一个状态去表示

好了,对于mybatis-plus的 逻辑删除乐观锁 分享到这里,如果您的项目中使用到mybatis-plus,这两个功能一定要用上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

石添的编程哲学

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

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

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

打赏作者

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

抵扣说明:

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

余额充值