mybatisplus使用OptimisticLockerInnerInterceptor实现版本号乐观锁

目录

OptimisticLockerInnerInterceptor 介绍

创建项目

创建项目

引入依赖

创建数据表

application.yml配置

项目结构

配置乐观锁拦截器

创建实体类

创建mapper

创建service

创建返回包装类BaseResponse

创建UserController

测试

查询

修改

​编辑

修改后再查询 

再次按版本号0修改 

修改时不传入版本号


OptimisticLockerInnerInterceptor 介绍

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

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

创建项目

创建项目

引入依赖

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.7</version>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

创建数据表

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`
(
    id BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
    name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
    age INT NULL DEFAULT NULL COMMENT '年龄',
    email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
    version INT not NULL DEFAULT 0 COMMENT '版本年龄',
    PRIMARY KEY (id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

DELETE FROM user;
 
INSERT INTO user (id, name, age, email,version) VALUES
(1, 'Jone', 18, 'test1@baomidou.com',0),
(2, 'Jack', 20, 'test2@baomidou.com',0),
(3, 'Tom', 28, 'test3@baomidou.com',0),
(4, 'Sandy', 21, 'test4@baomidou.com',0),
(5, 'Billie', 24, 'test5@baomidou.com',0);

application.yml配置

server:
  port: 8080

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://XXX:63306/user
    username: 
    password: 

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

项目结构

配置乐观锁拦截器

package com.sky.mybatisversiondemo.config;

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MybatisPlusConfig {

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

创建实体类

version字段需要添加@Version注解表名是版本号字段
package com.sky.mybatisversiondemo.entity;

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.Version;
import lombok.Data;


@Data
public class User {
    /**
     * 主键ID
     */
    @TableId(value = "id")
    private Long id;

    /**
     * 姓名
     */
    private String name;

    /**
     * 年龄
     */
    private Integer age;

    /**
     * 邮箱
     */
    private String email;
    /**
     * 版本号
     */
    @Version
    private Integer version;

}

创建mapper

package com.sky.mybatisversiondemo.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.sky.mybatisversiondemo.entity.User;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserMapper extends BaseMapper<User> {
}

创建service

这里利用了mybatisPlus的特性,提供了一些默认的查询。

UserService

package com.sky.mybatisversiondemo.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.sky.mybatisversiondemo.entity.User;

public interface UserService extends IService<User> {
}
UserServiceImpl
package com.sky.mybatisversiondemo.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sky.mybatisversiondemo.entity.User;
import com.sky.mybatisversiondemo.mapper.UserMapper;
import com.sky.mybatisversiondemo.service.UserService;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}

创建返回包装类BaseResponse

package com.sky.mybatisversiondemo.vo;

import lombok.Data;

@Data
public class BaseResponse<T> {
    protected int code = 0;
    protected String message = "成功";

    protected T data;

    public BaseResponse(int code, String message) {
        this.code = code;
        this.message = message;
    }

    public static <T> BaseResponse of(T data) {
        BaseResponse<T> response = new BaseResponse();
        response.setData(data);
        return response;
    }
    public BaseResponse() {
    }
}

创建UserController

package com.sky.mybatisversiondemo.controller;

import com.sky.mybatisversiondemo.entity.User;
import com.sky.mybatisversiondemo.service.UserService;
import com.sky.mybatisversiondemo.vo.BaseResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    @GetMapping("/list")
    public BaseResponse list(){
        List<User> list = userService.list();
        return BaseResponse.of(list);
    }

    @GetMapping("/ById")
    public  BaseResponse ById(Integer id){
        User user = userService.getById(id);
        if (user != null){
            return BaseResponse.of(user);
        }else {
            return new BaseResponse(500,"fail");
        }
    }

    /**
     * 插入学生信息
     * @param user
     */
    @PostMapping("/insert")
    public BaseResponse insertInfo(@RequestBody User user){
        boolean save = userService.save(user);
        if (save){
            return BaseResponse.of(save);
        }
        return new BaseResponse(500,"fail");
    }

    /**
     * 根据id更新学生表信息
     * @param user
     */
    @PutMapping("/update")
    public BaseResponse updateById(@RequestBody User user){
        boolean save = userService.updateById(user);
        if (save){
            return BaseResponse.of(save);
        }
        return new BaseResponse(500,"fail");
    }

    /**
     * 根据id删除学生信息
     * @param id
     */
    @DeleteMapping("/delete")
    public BaseResponse deleteById(String id){
        boolean b = userService.removeById(id);
        if (b){
            return BaseResponse.of(b);
        }
        return new BaseResponse(500,"fail");
    }

}

测试

查询

修改

修改是自动增加版本号,并且会增加版本号的判断,只有版本号一致才能修改成功。

日志

==>  Preparing: UPDATE user SET name=?, age=?, email=?, version=? WHERE id=? AND version=?
==> Parameters: Jone(String), 18(Integer), test1@baomidou.com(String), 1(Integer), 1(Long), 0(Integer)
<==    Updates: 1

修改后再查询 

此时版本号增加到1

再次按版本号0修改 

修改失败,因为版本号已经增加到了1,实现了乐观锁功能。

如果开发中遇到这种因为乐观锁修改失败的,则可以直接报错,或者再次查询数据后重试。推荐直接报错,修改失败,请重试。

修改时不传入版本号

则可以直接修改成功 ,但是修改后版本号不会增加,不推荐不传入版本号的修改。

日志

==>  Preparing: UPDATE user SET name=?, age=?, email=? WHERE id=?
==> Parameters: Jone(String), 18(Integer), test1@baomidou.com(String), 1(Long)
<==    Updates: 1

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值