Mybatis-Plus 乐观锁插件OptimisticLockerI及逻辑删除及防全局删除和更新

当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方式:

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

一、乐观锁插件实现步骤:

1、配置插件

@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
    return interceptor;
}

2、在实体类的字段上加上@Version注解

   /**
     * 版本
     */
    @Version//版本号,用于实现乐观锁(这个一定要加)
    @TableField(fill = FieldFill.INSERT)//添加这个注解是为了在后面设置初始值,不加也可以
    private Integer version;

3、配置MyMetaObjectHandler

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        this.setFieldValByName("createTime",new Date(),metaObject);
        this.setFieldValByName("updateTime",new Date(),metaObject);

        //设置版本号version的初始值为1
        //不加这个也可以,version的默认值为null,加了就是设置version的值从1开始
        this.setFieldValByName("version",1,metaObject);
    }

    //使用mp实现修改的操作,这个方法就会执行
    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
}

4、测试代码及结果

@SpringBootTest
class DemoApplicationTests {
	@Resource
	UserMapper userMapper;

	@Test
	public void testAdd() {
		User user = new User();
		user.setName("OrangeTest9");
		user.setAge(22);
		user.setEmail("1525@qq.com");
		int insert = userMapper.insert(user);
		System.out.println(insert);
	}

	/**
	 * 乐观锁实现方式:
	 * 1、取出记录时,获取当前version
	 * 2、更新时,带上这个version
	 * 3、执行更新时, set version = newVersion where version = oldVersion
	 * 4、如果version不对,就更新失败
	 */
	//测试乐观锁,看version的值是否加1
	@Test
	void testOptimisticLocker(){
		//根据id查询数据
		User user = userMapper.selectById(15);
		//进行修改
		user.setAge(21);
		userMapper.updateById(user);
	}
}	

先执行testAdd,再执行testOptimisticLocker,观察version值变化。
请添加图片描述
请添加图片描述
测试乐观锁,模拟失败场景

//测试乐观锁,模拟失败场景
	@Test
	void testOptimisticLockerFail(){
        //线程1
		//根据id查询数据
		User user1 = userMapper.selectById(3);
		user1.setAge(20);

		//线程2
		User user2 = userMapper.selectById(3);
		user2.setAge(28);

		//模拟另一个线程执行了插队操作
		userMapper.updateById(user2);
		userMapper.updateById(user1);
	}

执行结果:version已经更改,第二个SQL则执行失败!
请添加图片描述
在这里插入图片描述

二、配置逻辑删除

1、在yml中配置

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

2、实体类字段

    /**
     * 删除标志
    */
    @TableLogic
    private Integer deleted;

3、执行查询发现自动过滤deleted = 0的数据
请添加图片描述
三、防全局删除和更新
业务bug或者漏洞可能导致把整个表都更新或者删除,在生产环境中这是十分危险的事情,plus也考虑到了这一点,提供了防止全表更新与删除插件。

@Configuration
@MapperScan("com.example.demo.*")
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();

        // 添加防止全表更新与删除插件
        BlockAttackInnerInterceptor blockAttackInnerInterceptor=new BlockAttackInnerInterceptor();
        interceptor.addInnerInterceptor(blockAttackInnerInterceptor);

        return interceptor;
    }

}

单元测试

    //防止全表更新与删除插件
    @Test
    public void deleteAll() {
        //执行会报错: com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: Prohibition of full table deletion
        int delete = mapper.delete(null);
        System.out.println("删除成功"+delete);
        
        /* 改成根据条件删除,就不会报错*/
        QueryWrapper<Users> queryWrapper = new QueryWrapper();
        Users user = new Users();
        user.setName("三丰丰");
        queryWrapper.lambda().eq(Users::getName,"三丰丰");
        mapper.delete(queryWrapper);
        int delete2 = mapper.delete(null);
        System.out.println("删除成功"+delete2);

    }

    @Test
    public void updateAll() {
        LambdaUpdateWrapper<Users> updateWrapper = new LambdaUpdateWrapper<Users>().set(Users::getName, "三丰丰");
        mapper.update(null, updateWrapper);
        System.out.println("修改成功");
    }

防止全局删除结果1
在这里插入图片描述
防止全局更新2
在这里插入图片描述
参考文章
https://baomidou.com/pages/24112f/#%E7%89%B9%E6%80%A7

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值