关于SpringBoot整合MyBatis-Plus乐观锁不生效的问题解决方案

关于SpringBoot整合MyBatis-Plus乐观锁不生效的问题解决方案

SpringBoot整合Myabtis-Plus

在与官网配置一致的情况下依旧无法生效,如下整合mybatis-plus

1、依赖导入

<!--        mybatis-plus--> <dependency>     <groupId>com.baomidou</groupId>     <artifactId>mybatis-plus-boot-starter</artifactId>     <version>3.4.3.4</version> </dependency>

其余的springboot与mysql相关的依赖就无需展示

配置文件配置

mybatis-plus:   global-config:     db-config:       #      逻辑删除,删除标志       logic-delete-value: 1       #      逻辑删除,未删除标志       logic-not-delete-value: 0   type-aliases-package: com.fang.pojo   configuration:     #    mybatis-plus日志     log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

2、数据库插入

数据库以此为例

DROP TABLE IF EXISTS sys_user;  CREATE TABLE rbac_plus.sys_user (     id INT AUTO_INCREMENT NOT NULL COMMENT '主键ID',     name VARCHAR(50) NOT NULL COMMENT '名称',     password VARCHAR(500) NOT NULL COMMENT '密码',     email VARCHAR(200) NOT NULL  COMMENT '邮箱',     state INT NOT NULL DEFAULT 0 COMMENT '状态,0为正常,1为异常',     create_time DATETIME NOT NULL COMMENT '创建时间',     update_time DATETIME  COMMENT '修改时间',     deleted INT DEFAULT 0  COMMENT '假删除',     version INT DEFAULT 1  COMMENT '乐观锁',     PRIMARY KEY (id) )ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='user表';  INSERT INTO `rbac_plus`.`sys_user` (`name`, `password`, `email`, `create_time`) VALUES ('一号', '123', '[email protected]', CURRENT_DATE), 											('二号','234','234.qq.com',CURRENT_DATE), 											('三号','345','345.qq.com',CURRENT_DATE), 											('四号','456','456.qq.com',CURRENT_DATE), 											('五号','567','567.qq.com',CURRENT_DATE), 											('六号','678','678.qq.com',CURRENT_DATE);

3、SpringBoot各个层次的操作

3.1、实体类

/**  * @author FPH  * @since 2022.04.27 03点46分  */ @Data @TableName(sys_user) public class SysUser implements Serializable {     @TableId(type = IdType.AUTO)     private Integer id;      private String name;      private String password;       private String email;      private Integer state;      @TableField(fill = FieldFill.INSERT)     private Date createTime;      @TableField(fill = FieldFill.UPDATE)     private Date updateTime;      @TableLogic     private Integer deleted;      @Version     private Integer version;

@TableName指定表名

@TableId指定表的主键,并且定义这是一个自增的主键

@TableField表示填充此属性,

@TableLogic表示假删除

@Version表示乐观锁

以上配置均将在configuration层中实现

3.2、configuration

3.2.1、TableField的insert与update

insert表示插入这一数据时,自动将当前时间填充至此属性

update表示修改此数据时,自动将当前时间填充

这里官网有告诉我们如何配置:

package com.fang.configuration;  import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import org.apache.ibatis.reflection.MetaObject; import org.springframework.stereotype.Component;  import java.time.LocalDateTime;  /**  * @author FPH  * @since 2022年4月27日04:17:56  */ @Component public class MyMetaObjectHandler implements MetaObjectHandler {      @Override     public void insertFill(MetaObject metaObject) {         this.strictInsertFill(metaObject,createTime, LocalDateTime.class,LocalDateTime.now());     }      @Override     public void updateFill(MetaObject metaObject) {         // 起始版本 3.3.0(推荐)         this.strictUpdateFill(metaObject, updateTime, LocalDateTime.class, LocalDateTime.now());      } }

3.2.2、乐观锁配置

官网也有指出如何配置

package com.fang.configuration;  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;  /**  * @author FPH  * @since 2022.04.27 03点59分  */ @Configuration public class MybatisPlus {     /**      * 乐观锁      */     @Bean     public MybatisPlusInterceptor mybatisPlusInterceptor() {         MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();         interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());         return interceptor;     }  }

3.3、mapper层

package com.fang.mapper;  import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.fang.pojo.SysUser; import org.springframework.stereotype.Repository;  import java.util.List;  /**  * @author FPH  * @since 2022年4月27日04:04:16  */ @Repository public interface SysUserMapper extends BaseMapper<SysUser> { }

3.4、service层

package com.fang.service;  import com.baomidou.mybatisplus.extension.service.IService; import com.fang.pojo.SysUser;  import java.util.List;  /**  * @author FPH  * @since 2022年4月27日04:06:07  */ public interface SysUserService extends IService<SysUser> { }

实现类:

package com.fang.service.impl;  import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.fang.mapper.SysUserMapper; import com.fang.pojo.SysUser; import com.fang.service.SysUserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service;  import java.util.List;  /**  * @author FPH  * @since 2022年4月27日04:07:58  */ @Service(SysUserService) public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {     @Autowired     private SysUserMapper sysUserMapper; }

4、控制层测试

4.1、查询所有

package com.fang.controller;  import com.fang.pojo.SysUser; import com.fang.service.SysUserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;  import java.util.List;  /**  * @author FPH  * @since 2022年4月27日04:09:41  */ @RestController @RequestMapping(/sysUser) public class SysUserController {     @Autowired     private SysUserService sysUserService;        @GetMapping(/baseSelAll)     public List<SysUser> BaseSelectAll(){         return sysUserService.list();     } }

ApiPost测试,能够成功获取全部的集合

这里可以发现service层无需写这种简单地查询语句,即可实现基本的sql功能

4.2、根据id修改信息

这里能发现有时候乐观锁不能生效,例如以下例子:

package com.fang.controller;  import com.fang.pojo.SysUser; import com.fang.service.SysUserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;  import java.util.List;  /**  * @author FPH  * @since 2022年4月27日04:09:41  */ @RestController @RequestMapping(/sysUser) public class SysUserController {     @Autowired     private SysUserService sysUserService;         @PutMapping(updateById)     public String updateById(SysUser sysUser){         return sysUserService.updateById(sysUser)+;     } }

apiPost这样测试:

修改成功,但是去查看日志,发现并没有生效

乐观锁并没有自增


解决方案如下:

新增一个version

此时日志显示这样的信息:

数据库中成功自增

如果此时再修改,但version依旧是传1过去,则修改不成功

version与当前数据库不一致则修改失败

所以我们需要在每次修改时,传入一个version,通过id查询当前version的值,在通过set传入实体类中一起发送到mybatisPlus自带的修改方法中,则能实现乐观锁

4.3、假删除

前面的配置文件指定1表示已经被删除,0表示没被删除

控制层这样写:

package com.fang.controller;  import com.fang.pojo.SysUser; import com.fang.service.SysUserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*;  import java.util.Arrays; import java.util.List;  /**  * @author FPH  * @since 2022年4月27日04:09:41  */ @RestController @RequestMapping(/sysUser) public class SysUserController {     @Autowired     private SysUserService sysUserService;          @DeleteMapping(deleteByIds)     public String deleteById(Integer[] ids){         return sysUserService.removeByIds(Arrays.asList(ids))+;     } }

通过ids数组批量删除

删除成功

日志sql打印情况如下:

并不是真正地删除数据

插入在下一章记录,此时需要用到数据校验