首次接触MyBatis-Plus是在2018年年年底,因MyBatis-Plus的强大功能,目前不少公司都会引入,也深深吸引了我,我公司技术选型时我也会引入了MyBatis-Plus,在使用【若依】等框架时也会将其中的mybatis替换为mybatis-plus进行重构,遂通过MyBatis专栏将MyBatis和MyBatis-Plus的相关技术点安利给读者朋友,喜欢的点个赞吧,非常实用!
系列文章目录
第一章 myBatis分页插件pageHelper
第二章 MyBatis-Plus【1】—— 基本使用
第三章 MyBatis-Plus【2】——解锁MyBatis这些功能代码少些3成
第四章 Mybatis-Plus【3】——左手乐观锁、右手逻辑删除在数据层为所欲为
第五章 Mybatis Plus【4】—— 条件构造器 体系结构和详细案例
一、乐观锁
乐观锁是用来解决多线程情况下同一条数据同时可能被多人一起修改,造成数据紊乱的一种解决方案,当更新一条数据时,希望这条数据没有被别人更新,也就是说实现线程安全的数据更新。
判断有没有被修改的策略就是在准备更新时获取该数据的版本,在更新时检查版本是否相同,更新后将数据的版本修改来实现。
对于乐观锁和悲观锁的详细介绍可以参考 什么是乐观锁,什么是悲观锁 文章
1.1、实现方式
在Mybatis Plus步骤如下
- 取出记录时,获取当前version
- 更新记录时,带上这个version
- 执行更新时,set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
1.2、实现步骤
- 在数据表中新增
version
字段,类型为int
- 在实体类中新增
version
属性,并使用@Version
注解修饰 - 元数据处理接口添加 version 的
insert
默认值(可以不做,目的在于自动填充有个默认值而已) - 编写配置类,配置
乐观锁插件
1.3、数据库添加字段
基于 MyBatis-Plus【2】 也就是上篇文章的基础,在您自己的表中创建一个 version 字段,也可以按照下方sql实现:
ALTER TABLE `user` ADD COLUMN `version` INT
1.4、实体类
- @Version:实现乐观锁注解
- @TableField(fill = FieldFill.INSERT):实现自动填充,在新增数据时填充一个初始的版本号,当然您也可以设置数据库的默认值等方式
@Version
@TableField(fill = FieldFill.INSERT)
private Integer version;
1.5、元数据处理接口
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
// 使用MP实现添加操作,该方法执行
@Override
public void insertFill(MetaObject metaObject) {
......
this.setFieldValByName("version",1,metaObject);
}
// 使用MP实现修改操作,该方法执行
@Override
public void updateFill(MetaObject metaObject) {
......
}
}
1、支持的数据类型只有int、Integer、long、Long、Date、Timestamp、LocalDateTime
2、整数类型下newVersion
=oldVersion + 1
3、newVersion会写回到entity中
4、仅支持 updateById(id) 和 update(entity,warpper)方法
5、在update(entity,warpper)方法下,warpper不能重用
1.6、乐观锁配置类
@Configuration
@EnableTransactionManagement
@MapperScan(value = "com.buye.mp.mapper")
public class MyBatisPlusConfig {
/**
* 新版 插件配置方式
* @return
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return mybatisPlusInterceptor;
}
/**
* 旧版
* @Bean
* public OptimisticLockerInterceptor optimisticLockerInterceptor() {
* return new OptimisticLockerInterceptor();
* }
*/
}
1.7、测试
首先新增一条数据,因为有自动填充version,所以它的version是1,然后再根据id修改
@Test
public void addUser() {
// 创建User对象,并设置属性,此处没有设置id
User user = new User();
user.setName("不夜同学");
user.setEmail("test10.@baomidou.com");
user.setAge(14);
// 调用insert函数将用户添加进数据库
int row = userMapper.insert(user);
System.out.println("成功新增" + row + "条数据");
}
@Test
public void testOptimisticLokker() {
// 1、根据id查询数据
User user = userMapper.selectById(1452181379893747714L);
// 2、设置,修改数据
user.setAge(18);
userMapper.updateById(user);
}
效果图如下,默认version为1,修改后version为2
sql执行如下
二、逻辑删除
逻辑删除:假删除
,将对应数据中代表是否删除字段状态修改为 被删除状态
,之后数据仍然存在与数据库中;
物理删除:真实删除
:将对应数据从数据库中删除,之后查询不到此条被删除数据;
2.1、实现步骤
-
想数据库中添加
deleted
字段 -
实体类中添加
deleted
字段 -
元对象处理器接口添加
deleted
的 insert 默认值(可以不做,只是为了新增数据时有默认值) -
application.properties
加入配置 -
在配置类中配置Bean【mybatis plus高版本已经不需要配置了】
2.2、新增字段
ALTER TABLE `user` ADD COLUMN `deleted` boolean
2.3、实体类新增deleted字段
- @TableLogic:实现逻辑删除注解
@TableLogic
@TableField(fill = FieldFill.INSERT)
private Integer deleted;
2.4、application配置文件
该配置可以不做,默认0未删除,1以删除
# 逻辑删除已删除值(默认为1)
mybatis-plus.global-config.db-config.logic-delete-value=1
# 逻辑删除未删除值(默认为0)
mybatis-plus.global-config.db-config.logic-not-delete-value=0
2.5、测试
2.5.1、新增数据
@Test
public void addUser() {
// 创建User对象,并设置属性,此处没有设置id
User user = new User();
user.setName("不夜学长");
user.setEmail("test11.@baomidou.com");
user.setAge(14);
// 调用insert函数将用户添加进数据库
int row = userMapper.insert(user);
System.out.println("成功新增" + row + "条数据");
}
新增数据的deleted默认值为0,这里我们并没有设置自动填充哦!
2.5.2、删除数据
@Test
public void testLogicDelete() {
int row = userMapper.deleteById(1452267209106739202L);
System.out.println(row);
}
测试结果
2.5.3、添加逻辑删除后的查询
配置逻辑删除下的查询自带上 deleted = 0
条件
2.6、注意
如果需要查询出被逻辑删除的数据,那么就需要自己写sql语句啦
只对自动注入的sql起效:
- 插入: 不作限制
- 查找: 追加where条件过滤掉已删除数据,且使用 wrapper.entity 生成的where条件会忽略该字段
- 更新: 追加where条件防止更新到已删除数据,且使用 wrapper.entity 生成的where条件会忽略该字段
- 删除: 转变为 更新
例如:
- 删除:
update user set deleted=1 where id = 1 and deleted=0
- 查找:
select id,name,deleted from user where deleted=0
字段类型支持说明:
- 支持所有数据类型(推荐使用
Integer
,Boolean
,LocalDateTime
) - 如果数据库字段使用
datetime
,逻辑未删除值和已删除值支持配置为字符串null
,另一个值支持配置为函数来获取值如now()
附录:
- 逻辑删除是为了方便数据恢复和保护数据本身价值等等的一种方案,但实际就是删除。
- 如果你需要频繁查出来看就不应使用逻辑删除,而是以一个状态去表示
好了,对于mybatis-plus的 逻辑删除
和 乐观锁
分享到这里,如果您的项目中使用到mybatis-plus,这两个功能一定要用上。