MybatisPlus
基于狂神mybatisplus自整理笔记,可寻找对应视频参考该文章
通用mapper,和mybatisplus的区别
官网简介
MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window) 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生
特性
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
- 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
- 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
- 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
- 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
- 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
- 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
- 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
- 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
- 内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
- 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
官网-快速入门
https://baomidou.com/guide/quick-start.html#%E5%88%9D%E5%A7%8B%E5%8C%96%E5%B7%A5%E7%A8%8B
创建数据库
DROP TABLE IF EXISTS user; CREATE TABLE user ( id BIGINT(20) NOT NULL COMMENT '主键ID', name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名', age INT(11) NULL DEFAULT NULL COMMENT '年龄', email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱', PRIMARY KEY (id) );
id | name | age | |
---|---|---|---|
1 | Jone | 18 | test1@baomidou.com |
2 | Jack | 20 | test2@baomidou.com |
3 | Tom | 28 | test3@baomidou.com |
4 | Sandy | 21 | test4@baomidou.com |
5 | Billie | 24 | test5@baomidou.com |
插入对应的数据
DELETE FROM user; INSERT INTO user (id, name, age, email) VALUES (1, 'Jone', 18, 'test1@baomidou.com'), (2, 'Jack', 20, 'test2@baomidou.com'), (3, 'Tom', 28, 'test3@baomidou.com'), (4, 'Sandy', 21, 'test4@baomidou.com'), (5, 'Billie', 24, 'test5@baomidou.com');
创建工程
这里可以创建一个springboot的工程,也可以是一个maven工程
初始化一个springboot的项目
<!-- 导入依赖 mybatisplus的依赖 连接数据库的依赖 单元测试的依赖 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--这个包导入的时候需要指定一下版本,不然会报错--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.0.5</version> </dependency>
连接数据库
spring: datasource: username: root password: root url: jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8 driver-class-name: com.mysql.cj.jdbc.Driver ----------------------------------------------------------------------------------- # 数据库的连接信息 spring: datasource: # 这个顺序不讲究 driver-class-name: com.mysql.cj.jdbc.Driver username: root password: root url: jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
pojo
package com.qr.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class User { private long id; private String name; private Integer age; private String email; }
mapper
执行过程中
当我在将这个mapper和这个Repository全部都给注释掉会后
只要在启动类上能够扫描到该接口,改接口中的还是会放到容器中的
所以这两个可以省略,只要添加了MapScan
//表示是一个mapper接口,放到容器中 //@Mapper @Repository public interface UserMapper extends BaseMapper<User> { }
启动
@SpringBootApplication @MapperScan("com.qr.mapper") public class MybatisplusTestApplication { public static void main(String[] args) { SpringApplication.run(MybatisplusTestApplication.class, args); } }
测试
import com.qr.pojo.User; import com.qr.mapper.UserMapper; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import java.util.List; @SpringBootTest class MybatisplusTestApplicationTests { @Autowired private UserMapper userMapper; @Test void contextLoads() { //查询全部,wrapper是一个条件构造器 List<User> users = userMapper.selectList(null); users.forEach(System.out::println); } }
crud
添加
/* 添加 */ @Test void insert(){ //参数需要一个对象 User user = new User(); /* 如果使用的lombok中生成的方法,那么导入maven后,idea中还是需要添加插件的 不然不会存在相应的方法 */ user.setName("zhangsan"); user.setAge(22); user.setEmail("357886376"); userMapper.insert(user); }
因为我的数据库第一遍添加的时候没有选择id,但是是自动生成到了0号位置
此时再次添加其他数据的时候会出现下面的异常
@Test
void insert(){
//参数需要一个对象
//User user = new User();
/*
如果使用的lombok中生成的方法,那么导入maven后,idea中还是需要添加插件的
不然不会存在相应的方法
*/
/*user.setName("zhangsan");
user.setAge(22);
user.setEmail("357886376");
userMapper.insert(user);
*/
//这个社会的顺序是讲究的
User user1 = new User();
user1.setName("lisi");
user1.setAge(2);
user1.setEmail("hfhasjfas");
userMapper.insert(user1);
}
==========================================================================================
org.springframework.dao.DuplicateKeyException:
### Error updating database. Cause: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '0' for key 'user.PRIMARY'
### The error may involve com.qr.mapper.UserMapper.insert-Inline
### The error occurred while setting parameters
### SQL: INSERT INTO user ( id, name, age, email ) VALUES ( ?, ?, ?, ? )
### Cause: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '0' for key 'user.PRIMARY'
; Duplicate entry '0' for key 'user.PRIMARY'; nested exception is java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '0' for key 'user.PRIMARY'
查看我们的表中,我们的主键是非空且唯一的
mysql在批量插入数据的时候,如果有一个字段具有unique约束,而插入数据重复的话,
就会抛出DuplicateKeyException导致后续数据无法插入
主键没有设置,这里可以选择点击自增来完成,或者自己设置一个表中没有主键字段
SQLIntegrityConstraintViolationException: Duplicate entry xxx for key 这个错误,
这个错误的意思是:违反唯一约束条件,也即该字段设置是唯一的,但是数据插入时,报错相同记录的数据
User user1 = new User(); user1.setId(6); user1.setName("lisi"); user1.setAge(2); user1.setEmail("hfhasjfas"); userMapper.insert(user1);
当设置主键不冲突之后,就可以正常插入了
一般在SQL中我们的主键也因该是自增的,那么我们也可以执行SQL修改主键为自增的策略
??? 执行不了
ALTER TABLE USER MODIFY id INT AUTO_INCREMENT PRIMARY KEY;
ALTER TABLE USER ADD id INT AUTO_INCREMENT;
???
修改不了我重新创建
DROP TABLE IF EXISTS USER; CREATE TABLE USER ( id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID', NAME VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名', age INT(11) NULL DEFAULT NULL COMMENT '年龄', email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱', PRIMARY KEY (id) );
修改实体类完成
给实体类添加相应的注解来完成主键的增长
@Data @AllArgsConstructor @NoArgsConstructor public class User { /** * @TableId是一个枚举类: * AUTO(0),主键自增,这个配置要求数据库也是自增的 * NONE(1),不使用自增 * INPUT(2),手动输入 * ID_WORKER(3),全局唯一id * UUID(4),全局唯一id * ID_WORKER_STR(5);全局唯一字符串 */ @TableId(type = IdType.ID_WORKER) private long id; private String name; private Integer age; private String email; }
删除
/** * 删除 */ @Test void delete(){ int i = userMapper.deleteById(1L); System.out.println(i); } /** * 批量删除 */ @Test void testDeletePiliang(){ int i = userMapper.deleteBatchIds(Arrays.asList(2, 3)); System.out.println(i); }
逻辑删除
物理删除:直接删除
逻辑删除:变量查询,查询不到,防止数据的丢失
给数据库中字段添加一列isdelete
ALTER TABLE USER ADD COLUMN is_delete INT DEFAULT 0;
实体类中添加对用的属性
/** * @TableLogic逻辑删除 */ @TableLogic private Integer isDelete;
添加逻辑删除组件
import com.baomidou.mybatisplus.core.injector.ISqlInjector; import com.baomidou.mybatisplus.extension.injector.LogicSqlInjector; import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor; import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.annotation.EnableTransactionManagement; //管理事务 @EnableTransactionManagement //可以将MapScan挪到这里,因为这里是MybatisPlus的配置类,让这里去扫描 @Configuration public class MybatisPlusConfig { //注册乐观锁插件 @Bean public OptimisticLockerInterceptor optimisticLockerInterceptor() { return new OptimisticLockerInterceptor(); } /** * 分页插件 * @return */ @Bean public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); } /** * 逻辑删除 */ @Bean public ISqlInjector sqlInjector(){ return new LogicSqlInjector(); } }
配置yml
# 数据库的连接信息
spring:
datasource:
# 这个顺序不讲究
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: root
url: jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
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)
测试,再次删除数据,看is_delete的值
修改
/** * 修改 */ @Test void update(){ User user = new User(); user.setId(2L); user.setName("hello"); user.setAge(12); user.setEmail("8888888888"); userMapper.updateById(user); }
查找
/* 查询 */ @Test void select(){ User user = userMapper.selectById(1L); System.out.println(user); }
分页查询
首先配置分页的拦截器
//管理事务 @EnableTransactionManagement //可以将MapScan挪到这里,因为这里是MybatisPlus的配置类,让这里去扫描 @Configuration public class MybatisPlusConfig { //注册乐观锁插件 @Bean public OptimisticLockerInterceptor optimisticLockerInterceptor() { return new OptimisticLockerInterceptor(); } /** * 分页插件 * @return */ @Bean public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); } }
这里面就自带了一个分页对象
/** * 测试分页插件 */ @Test void testPage(){ /** * 参数1,当前也,参数2,页面的大小 */ Page<User> page = new Page<>(1, 2); userMapper.selectPage(page,null); page.getRecords().forEach(System.out::println); //总共几条记录 System.out.println(page.getTotal()); }
自动填充:
Mysql中的日期类型
Mysql中经常用来存储日期的数据类型有三种:Date、Datetime、Timestamp。
【1】Date数据类型:用来存储没有时间的日期。Mysql获取和显示这个类型的格式为“YYYY-MM-DD”。支持的时间范围为“1000-00-00”到“9999-12-31”。
【2】Datetime类型:存储既有日期又有时间的数据。存储和显示的格式为 “YYYY-MM-DD HH:MM:SS”。支持的时间范围是“1000-00-00 00:00:00”到“9999-12-31 23:59:59”。
【3】Timestamp类型:也是存储既有日期又有时间的数据。存储和显示的格式跟Datetime一样。支持的时间范围是“1970-01-01 00:00:01”到“2038-01-19 03:14:07”
原文链接:https://blog.csdn.net/qq_35860138/article/details/88957739
对于表的创建时间和修改时间应该是自动的添加到表当中的,而不是我们每次都要手动的设置
给数据库和实体类添加相应的字段
ALTER TABLE USER ADD COLUMN create_Time TIMESTAMP;
ALTER TABLE USER ADD COLUMN update_Time TIMESTAMP;
实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
/**
* @TableId是一个枚举类:
* AUTO(0),主键自增,这个配置要求数据库也是自增的
* NONE(1),不使用自增
* INPUT(2),手动输入
* ID_WORKER(3),全局唯一id
* UUID(4),全局唯一id
* ID_WORKER_STR(5);全局唯一字符串
*/
@TableId(type = IdType.AUTO)
private long id;
private String name;
private Integer age;
private String email;
/**
* 创建时间
* DEFAULT,默认不操作
* INSERT,填充策略,插入时触发
* UPDATE,更新时触发
* INSERT_UPDATE;插入更新都触发
*/
@TableField(fill = FieldFill.INSERT)
private Date createTime;
//修改时间
@TableField(fill = FieldFill.UPDATE)
private Date updateTime;
}
处理器处理
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.reflection.MetaObject; import org.springframework.stereotype.Component; import java.util.Date; /** * 日期处理器 */ @Slf4j @Component public class MyDateHandler implements MetaObjectHandler { /** * 插入时的填充策略 * @param metaObject */ @Override public void insertFill(MetaObject metaObject) { log.info("start insert fill ...."); /** * 参数: * 1:给哪个字段插入值 * 2:更新时间 * 3:创建时间 */ this.setFieldValByName("createTime", new Date(), metaObject); this.setFieldValByName("updateTime", new Date(), metaObject); } /** * 更新时的填充策略 * @param metaObject */ @Override public void updateFill(MetaObject metaObject) { log.info("start update fill ...."); this.setFieldValByName("updateTime", new Date(), metaObject); } }
插入测试
这个类加入到spring容器中就可以了
@Test void insert(){ User user1 = new User(); user1.setName("zhaoliu"); user1.setAge(22); user1.setEmail("hfhasjfas"); userMapper.insert(user1); }
这样就可以插入成功,而且显示日期,由于表是重新创建的没有插入数据,所以是1
条件构造器
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qr.mapper.UserMapper;
import com.qr.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
import java.util.Map;
@SpringBootTest
public class WrapperTests {
@Autowired
private UserMapper userMapper;
/**
* 条件构造器的使用
* SELECT * FROM USER WHERE NAME IS NOT NULL AND email IS NOT NULL AND age > 15;
*/
@Test
void selectWrapper(){
//参数需要一个Wrapper<User>
QueryWrapper<User> wrapper = new QueryWrapper<>();
//构造条件,name,email这列不为空,age>15岁的人
wrapper.isNotNull("name").isNotNull("email").
ge("age",15);
userMapper.selectList(wrapper).forEach(System.out::println);
}
@Test
void selectNameWrapper(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
//select * from user where name = sandy
wrapper.eq("name","Sandy");
User user = userMapper.selectOne(wrapper);
System.out.println(user);
}
/**
* SELECT * FROM USER WHERE age BETWEEN 15 AND 20;
*/
@Test
void betweenWrapper(){
//查询年龄范围
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.between("age", 15, 20);
Integer integer = userMapper.selectCount(wrapper);
System.out.println(integer);
}
/**
* 模糊查询
*/
@Test
void selectMohu(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
/**
* 查询name中包含s的
* email中左边以t开头的
* name中右边以e结尾的
*/
wrapper.notLike("name","s")
.likeLeft("email","t")
.likeRight("name","e");
List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
maps.forEach(System.out::println);
}
/**
* 连接查询
* SELECT * FROM USER WHERE age IN (SELECT age FROM USER WHERE age > 15);
*/
@Test
void selectInner(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.inSql("age","select age from user where age>15");
List<Object> objects = userMapper.selectObjs(wrapper);
objects.forEach(System.out::println);
}
/**
* 排序
* SELECT * FROM USER ORDER BY age DESC;
*/
@Test
void selectSort(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.orderByDesc("age");
List<User> users = userMapper.selectList(wrapper);
users.forEach(System.out::println);
}
}
代码生成器
添加依赖
<dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity-engine-core</artifactId> <version>2.3</version> </dependency>
编写代码生成器逻辑
package com.qr;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import java.util.ArrayList;
/**
* 代码生成器
* 1:构建代码生成器对象
* 2:配置策略
*
*
*/
public class CodeSoEasy {
public static void main(String[] args) {
//构建代码生成器对象
AutoGenerator mpg = new AutoGenerator();
//全局配置
GlobalConfig gc = new GlobalConfig();
//获取当前项目的路径
String projectPath = System.getProperty("user.dir");
//设置生成代码的输出路径
gc.setOutputDir(projectPath+"/src/main/java");
//设置作者
gc.setAuthor("穷人");
//是否打开资源管理器,不打开
gc.setOpen(false);
//是否覆盖原来生成的代码
gc.setFileOverride(false);
//去掉service的I前缀
gc.setServiceName("%sService");
//设置主键的生成策略
gc.setIdType(IdType.ID_WORKER);
//设置日期类型
gc.setDateType(DateType.ONLY_DATE);
//是否配置swagger文档
gc.setSwagger2(true);
//将全局配置丢入到自动生成器当中
mpg.setGlobalConfig(gc);
//设置数据源
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("root");
//设置使用数据库的驱动
dsc.setDbType(DbType.MYSQL);
mpg.setDataSource(dsc);
//设置包的配置
PackageConfig pc = new PackageConfig();
//设置模块名称
pc.setModuleName("erp");
//设置类路径
pc.setParent("com.qr");
//设置实体类的名称
pc.setEntity("pojo");
pc.setMapper("mapper");
pc.setService("service");
pc.setController("controller");
mpg.setPackageInfo(pc);
//策略配置
//创建策略配置对象
StrategyConfig strategy = new StrategyConfig();
//设置要映射的表名
strategy.setInclude("user");
//设置包命名的规则,下划线转驼峰命名
strategy.setNaming(NamingStrategy.underline_to_camel);
//列名也支持下划线转驼峰
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
//自动生成Lombok
strategy.setEntityLombokModel(true);
//逻辑删除的名称
strategy.setLogicDeleteFieldName("deleted");
//设置字段自动填充
TableFill gmtCreate = new TableFill("gmt_create", FieldFill.INSERT);
TableFill gmtModified = new TableFill("gmt_modified", FieldFill.INSERT_UPDATE);
ArrayList<TableFill> tableFills = new ArrayList<>();
//将自动填充的策略进行添加
tableFills.add(gmtCreate);
tableFills.add(gmtModified);
//参数是一个list,需要创建一个list
strategy.setTableFillList(tableFills);
//乐观锁配置
strategy.setVersionFieldName("version");
//开启restful的驼峰命名
strategy.setRestControllerStyle(true);
//将网站url变为带下划线的形式
strategy.setControllerMappingHyphenStyle(true);
mpg.setStrategy(strategy);
//执行代码
mpg.execute();
}
}
MybatisPlus乐观锁
当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方式:
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
使用方式:字段上加上
@Version
注解给表中字段添加一个version
version中默认值设为1
ALTER TABLE USER MODIFY COLUMN VERSION INT DEFAULT 1;
import com.baomidou.mybatisplus.annotation.*; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.util.Date; @Data @AllArgsConstructor @NoArgsConstructor public class User { /** * @TableId是一个枚举类: * AUTO(0),主键自增,这个配置要求数据库也是自增的 * NONE(1),不使用自增 * INPUT(2),手动输入 * ID_WORKER(3),全局唯一id * UUID(4),全局唯一id * ID_WORKER_STR(5);全局唯一字符串 */ @TableId(type = IdType.AUTO) private long id; private String name; private Integer age; private String email; /** * 创建时间 * DEFAULT,默认不操作 * INSERT,填充策略,插入时触发 * UPDATE,更新时触发 * INSERT_UPDATE;插入更新都触发 */ @TableField(fill = FieldFill.INSERT) private Date createTime; //修改时间 @TableField(fill = FieldFill.UPDATE) private Date updateTime; /** * 数据库字段同步实体类 * @Version代表这个是mybatisplus的一个乐观锁的注解 */ @Version private Integer version; }
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.annotation.EnableTransactionManagement; //管理事务 @EnableTransactionManagement //可以将MapScan挪到这里,因为这里是MybatisPlus的配置类,让这里去扫描 @Configuration public class MybatisPlusConfig { //注册乐观锁插件 /** * 旧版 */ @Bean public OptimisticLockerInterceptor optimisticLockerInterceptor() { return new OptimisticLockerInterceptor(); } }
这样设置之后啥也不用管,直接测试
@Test void testOptimisticLockerInnerInterceptor(){ User user = userMapper.selectById(1L); user.setName("Mybatisplus"); user.setAge(22); user.setEmail("357886376"); userMapper.updateById(user); }
这样之后查看数据库版本信息就会发生相应的变化