MyBatis-Plus —— 扩展

本文介绍了如何在MyBatis-Plus中使用逻辑删除功能,包括数据库字段设计、实体类配置以及乐观锁的版本号实现。此外,还讨论了如何防止全表更新和删除操作,以增强数据安全性。

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

MyBatis-Plus 扩展

1.逻辑删除

逻辑删除:假删除、将对应数据中代表是否被删除字段的状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录。

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

当删除数据的时候,自定修改此列的属性值 1:逻辑删除 0:未逻辑删除
当查询数据的时候,默认只查询 deleted =0 ,即逻辑未删除的数据

逻辑删除实现

  • 数据库 添加一个表字段deleted
ALTER TABLE USER ADD deleted INT DEFAULT 0 ;  # int 类型 1  逻辑删除 0 未逻辑删除
  • 实体类 添加逻辑删除属性

单一指定

@TableLogic
private Integer deleted;

yml配置类 全局指定

mybatis-plus:
  global-config:
    db-config:
      #逻辑删除的属性
      logic-delete-field: deleted  #字段名
#      #默认  可改
#      logic-delete-value: 0   # 删除
#      logic-not-delete-value: 1   #未删除

测试

@SpringBootTest
public class MyBatisPlusTableLogicTest {

    @Autowired
    private UserMapper userMapper;

    @Test
    public void test1(){
        //delete from user where id=1 物理删除
        //-> update user set daleted=1 where id=1 and deleted=0
        userMapper.deleteById(1);
    }

}

==>  Preparing: UPDATE t_user SET deleted=1 WHERE id=? AND deleted=0

2.乐观锁实现

2.1 乐观锁和悲观锁

乐观锁和悲观锁是在并发编程中用于处理并发访问和资源竞争的两种不同的锁机制!!

悲观锁:
悲观锁的基本思想是,在整个数据访问过程中,将共享资源锁定,以确保其他线程或进程不能同时访问和修改该资源。悲观锁的核心思想是"先保护,再修改"。在悲观锁的应用中,线程在访问共享资源之前会获取到锁,并在整个操作过程中保持锁的状态,阻塞其他线程的访问。只有当前线程完成操作后,才会释放锁,让其他线程继续操作资源。这种锁机制可以确保资源独占性和数据的一致性,但是在高并发环境下,悲观锁的效率相对较低。

乐观锁:
乐观锁的基本思想是,认为并发冲突的概率较低,因此不需要提前加锁,而是在数据更新阶段进行冲突检测和处理。乐观锁的核心思想是"先修改,后校验"。在乐观锁的应用中,线程在读取共享资源时不会加锁,而是记录特定的版本信息。当线程准备更新资源时,会先检查该资源的版本信息是否与之前读取的版本信息一致,如果一致则执行更新操作,否则说明有其他线程修改了该资源,需要进行相应的冲突处理。乐观锁通过避免加锁操作,提高了系统的并发性能和吞吐量,但是在并发冲突较为频繁的情况下,乐观锁会导致较多的冲突处理和重试操作。

注:悲观锁和乐观锁是两种解决并发数据问题的思路,不是具体技术!!!

具体技术和方案:

  1. 乐观锁实现方案和技术:
    • 版本号/时间戳:为数据添加一个版本号或时间戳字段,每次更新数据时,比较当前版本号或时间戳与期望值是否一致,若一致则更新成功,否则表示数据已被修改,需要进行冲突处理。
    • CAS(Compare-and-Swap):使用原子操作比较当前值与旧值是否一致,若一致则进行更新操作,否则重新尝试。
    • 无锁数据结构:采用无锁数据结构,如无锁队列、无锁哈希表等,通过使用原子操作实现并发安全。
  2. 悲观锁实现方案和技术:
    • 锁机制:使用传统的锁机制,如互斥锁(Mutex Lock)或读写锁(Read-Write Lock)来保证对共享资源的独占访问。
    • 数据库锁:在数据库层面使用行级锁或表级锁来控制并发访问。
    • 信号量(Semaphore):使用信号量来限制对资源的并发访问。

2.2 乐观锁保证数据一致性:版本号判断

实现流程:

  • 每条数据添加一个版本号字段version
  • 取出数据时,获取当前version 【防止并发数据更新时出现错误数据】
  • 更新时,再次检查 获取的version与数据库最新version是否一致
  • 如果version一致,证明没有人修改数据,再执行更新,set 数据 ,version+1
  • 如果version不一致,证明该数据已经被修改,取出的数据已经失效,即更新失败

2.3 使用 MyBatis-Plus 数据使用乐观锁

步骤:

  • 添加版本号更新插件,使用拦截器,完成版本对比,版本自增+1
@Bean
public MybatisPlusInterceptor plusInterceptor(){

    //todo:mybatis-plus的插件集合[将所需插件加入到这个集合中即可,如分页插件、乐观锁插件..]
    MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();

    //分页插件
    mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));

    //乐观锁【版本号插件】 mybatis-plus会在更新时自动对比版本号字段和 version+1
    mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());

    return  mybatisPlusInterceptor;
}
  • 数据库添加字段version , 实体类添加@Version private Integer version
ALTER TABLE t_user ADD VERSION INT DEFAULT 1 ;  # int 类型 乐观锁字段
//todo:版本号字段
    @Version
    private Integer version;
  • 正常更新使用
//演示乐观锁生效场景
@Test
public void test1(){
    //步骤1: 先查询,在更新 获取version数据
    //同时查询两条,但是version唯一,最后更新的失败
    User user  = userMapper.selectById(5); // version=1
    User user1  = userMapper.selectById(5); // version=1

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

    userMapper.updateById(user); // 20  v=1 检查 v=1 version一致 执行更新 + version+1=2

    //乐观锁生效,失败!
    userMapper.updateById(user1); // 获取的version=1,检查version=2,1!=2 失效数据,修改失败
}

3.防止全表更新和删除实现

针对 update 和 delete 语句 作用: 阻止恶意的全表更新删除

添加防止全表更新和删除拦截器

@Bean
public MybatisPlusInterceptor plusInterceptor(){
    //todo:mybatis-plus的插件集合[将所需插件加入到这个集合中即可,如分页插件、乐观锁插件..]
    MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();

    //分页插件
    mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));

    //乐观锁【版本号插件】 mybatis-plus会在更新时自动对比版本号字段和 version+1
    mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());

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

    return  mybatisPlusInterceptor;
}
@Test
public void testDelete(){

    //全表删除  拦截报错
    userMapper.delete(null);
    // Caused by: com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: Prohibition of table update operation
    
    //全表更新  拦截报错
    User user = new User();
    user.setName("xxxxx");
    user.setEmail("xxxx@qq.com");
    userMapper.update(user,null);
    //Caused by: com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: Prohibition of table update operation
}

4.mybatisx

https://baomidou.com/pages/ba5b24/

### MyBatis-Plus 插件的功能介绍 MyBatis-Plus 是一款基于 MyBatis 的增强工具,旨在简化开发者的数据库操作流程并提高开发效率。该框架提供了多种内置插件来扩展其核心功能,使得开发者能够更灵活地应对复杂多变的业务场景。 #### 支持丰富的插件扩展机制 MyBatis-Plus 提供了丰富的插件扩展机制,允许开发者通过编写自定义插件实现特定的需求或优化性能[^1]。这些插件可以在不修改原有代码的基础上增加新特性,比如分页查询、SQL执行分析等功能。 #### 易于集成到Spring Boot项目中 对于采用 Spring Boot 构建的应用程序来说,集成本地环境下的 MyBatis-Plus 非常简单。只需要按照常规方式配置依赖项即可完成基本设置;而对于IDEA用户而言,则可以通过安装专门设计用于提升工作效率的 `mybatisX` 插件进一步加速开发过程[^2]。 #### IntelliJ IDEA 中的具体应用指导 为了使初学者更快地上手使用 MyBatis-Plus 及其相关插件,在 IntelliJ IDEA 这样的主流 IDE 上也有详细的入门指南提供给广大程序员参考学习。这不仅有助于理解各个组件之间的协作关系,同时也展示了实际编码过程中可能遇到的一些常见问题及其解决方案[^3]。 #### 扩展能力:支持多表联合查询 值得注意的是,除了官方提供的标准版之外,社区还贡献了许多第三方插件以弥补某些方面的不足之处——例如当面对需要处理多个相互关联的数据表时,“Mybatis-Plus-Plus” 就是一个很好的例子。它有效地解决了原生版本仅限于单一表格操作这一局限性,并且实现了更加高效便捷的关系型数据检索方法[^4]。 --- ```xml <!-- Maven 依赖 --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>x.x.x</version> </dependency> <!-- 如果要使用 mybatis-plus-plus 插件 --> <dependency> <groupId>io.github.nullbull</groupId> <artifactId>mybatis-plus-plus</artifactId> <version>y.y.y</version> </dependency> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值