04-MybatisPlus实现乐观锁

乐观锁与悲观锁

乐观锁

认为自己在使用数据时不会有别的线程修改数据,所以不会添加锁,只在更新数据的时候判断之前有没有别的线程更新了这个数据。如果有被别的线程更新,则再次重试更新。

悲观锁

认为自己在使用数据时一定有别的线程来修改数据,所以在获取数据的时候会先加锁,确保数据不会被别的线程修改。

MybatisPlus实现乐观锁

实现原理
  1. 查询记录时,获取当前记录的version(版本号)
  2. 更新步骤1查询出的记录时,使用version,作为更新条件,并且执行更新时,要给version字段赋新值
  3. 如果version不对,就更新失败

代码原理如下:

# 1、查询记录
select id,name,age,sex,version from person where id = 001;
# 假设查出来的记录是:001,王二,30,男,1

# 2、更新时,使用version作为更新条件,并且给version赋新值
update person
set name = '张三',
version = 2
where id = 001
and version = 1;

# 3. 此时,在做更新时,如果version的值,已经被别的线程抢先更新了,不再等于1,那么步骤2就会执行失败;要实现更新,重试即可。
实现步骤
  1. 新增数据库表字段,语句如下:
ALTER TABLE mybatis_plus_user ADD COLUMN `version` INT(32) DEFAULT 1 COMMENT '乐观锁'; 
  1. 新增对应实体类字段
/**
  * 乐观锁版本号
  */
 @Version
 private Integer version;
  1. 注册组件
package springboot.mybatisplus.config;

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * @Description MybatisPlus配置类
 * @ClassName MybatisPlusConfig
 * @Author yuhuofei
 * @Date 2022/4/3 15:20
 * @Version 1.0
 */
@Configuration
@EnableTransactionManagement
@MapperScan("springboot.mybatisplus.mapper")
public class MybatisPlusConfig {

    //注册乐观锁插件
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return mybatisPlusInterceptor;
    }
}

测试
  1. 在测试类中,新增一个测试方法
@Test
public void testOptimisticLocker() {
    //查询一条记录
    MybatisPlusUser mybatisPlusUser = mybatisPlusUserMapper.selectById(1508489260037705729L);

    //更新
    mybatisPlusUser.setName("张三");
    mybatisPlusUser.setAge(30);
    mybatisPlusUserMapper.updateById(mybatisPlusUser);
}
  1. 执行,具体执行过程如下
JDBC Connection [HikariProxyConnection@344080246 wrapping com.mysql.cj.jdbc.ConnectionImpl@6917bb4] will not be managed by Spring
==>  Preparing: SELECT id,name,age,email,create_time,update_time,version FROM mybatis_plus_user WHERE id=?
==> Parameters: 1508489260037705729(Long)
<==    Columns: id, name, age, email, create_time, update_time, version
<==        Row: 1508489260037705729, hahaha, 28, 1ddgds97@qq.com, 2022-03-29 01:00:41, 2022-03-29 01:01:41, 1
<==      Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@23706db8]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@48528634] was not registered for synchronization because synchronization is not active
2022-04-03 15:35:37.675  INFO 14740 --- [           main] s.m.handle.MyMetaObjectHandler           : start update fill ....
JDBC Connection [HikariProxyConnection@243596165 wrapping com.mysql.cj.jdbc.ConnectionImpl@6917bb4] will not be managed by Spring
==>  Preparing: UPDATE mybatis_plus_user SET name=?, age=?, email=?, create_time=?, update_time=?, version=? WHERE id=? AND version=?
==> Parameters: 张三(String), 30(Integer), 1ddgds97@qq.com(String), 2022-03-29 01:00:41.0(Timestamp), 2022-03-29 01:01:41.0(Timestamp), 2(Integer), 1508489260037705729(Long), 1(Integer)
<==    Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@48528634]
  1. 结果

在这里插入图片描述

  1. 注意点
    如果当前更新失败,说明version字段在查询之后,被其它线程抢先更新了;此时如果依旧想继续更新,那么重新执行一遍方法即可。
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值