目录
引言
在现代软件开发中,数据库操作是不可或缺的一环。为了提高系统的性能、安全性以及数据一致性,开发者需要深入了解一些高级的数据库操作技术。本篇博客将深入探讨三个重要的数据库操作技术:逻辑删除、乐观锁和分页插件。通过深度讲解这些技术,读者将能够更好地应对实际项目中的复杂场景。
1. 逻辑删除
1.1 概述
MyBatis-Plus
中的逻辑删除(Logical Delete)是在数据库中进行虚拟删除,即实际删除数据时,并不会将数据从数据库中删除,而是通过一个标记来记录其已被删除。这种删除方式称为逻辑删除或软删除。
1.2 逻辑删除的优势
逻辑删除相比物理删除具有以下优势:
数据恢复: 可以方便地通过修改记录的状态来实现数据的恢复,而无需进行繁琐的数据库恢复操作。
历史记录: 可以保留数据删除的历史记录,方便日后审计和分析。
1.3.为什么使用逻辑删除
当我们使用物理删除时,数据将被永久删除,无法恢复。但有些情况下,我们并不希望永久删除数据,比如用户误删除、操作失误等情况,这时逻辑删除就尤为重要。
另外,逻辑删除还可以对应业务层逻辑,将数据状态标志为“已删除”,便于后续查询和统计。同时,逻辑删除还能提高删除操作效率,减少物理删除数据对系统性能的影响。
1.4 综合案例
配置yml
global-config:
db-config:
logic-delete-field: state# 全局逻辑删除的实体字段名
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
数据表增加字段state
实体类添加对应的字段state(与yml的要一致!)
@TableField()
private intstate;
此时使用mybatisplus删除就会把state从0变为1,之后查询只会显示未0的
id为1的state字段0改为1
此时id为1已经逻辑删除掉了
2. 乐观锁和悲观锁
2.1.什么是乐观锁和悲观锁
乐观锁( Optimistic Locking )和悲观锁是数据库中的两种并发控制机制。
乐观锁假定数据一般情况下不会发生冲突,因此在读取数据时不会对其加锁,而是在写入时先比较数据版本号(比如时间戳)是否相同,再进行操作。如果版本号相同,则表示该数据没有被其他进程修改,可以进行写操作;如果版本号不同,则表示该数据已经被其他进程修改,写操作会失败,需要重新读取数据进行操作。
乐观锁是为了解决并发过程中数据更新冲突的问题,乐观锁能提高并发过程中的程序吞吐量。
悲观锁则假定数据会发生冲突,因此在读取数据时就会对其加锁,防止其他进程同时修改此数据,直到当前进程操作完成并解锁后,其他进程才能再次操作该数据。
2.2.乐观锁和悲观锁的区别
乐观锁和悲观锁的区别主要有以下几点:
- 加锁时间不同:乐观锁在读取数据时不会对其加锁,而是在写入时进行比较和加锁操作;悲观锁在读取数据时就会对其加锁。
- 冲突处理方式不同:乐观锁会在写入时进行比较和冲突检测,如果版本号不一致则操作失败,需要重新读取数据;悲观锁则会阻塞其他进程对该数据的访问,直到当前进程完成操作并解锁。
- 适用场景不同:乐观锁适用于并发量比较小、数据量比较大、操作更多为读取的场景;悲观锁适用于并发量比较大、数据量比较小、操作更多为写入的场景。
总的来说,乐观锁适用于并发冲突较少的场景,可以提高系统的并发性;悲观锁适用于并发冲突较多的场景,可以保证数据的一致性和安全性。
2.3.综合案例
使用数据版本(Version)记录机制实现乐观锁,这是乐观锁最常用的一种实现方式。
在表中添加一个version字段,默认值为1
实体类上添加@Version注解
@Version
private Integer version;
导入插件
package com.yuan.ttx.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;
// Spring Boot 方式
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return mybatisPlusInterceptor;
}
}
然后Controller中
这个是可行的,先查询在修改,然后version+1+1
上面代码就被乐观锁锁住了,对同一个对象操作,查询后没修改,又查询,再修改,此时Version没有进行+1,任然是2然后最后的结果是第一个成功,第二个不成功
3. 分页插件
在类中添加下面代码
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
package com.yuan.ttx.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
// Spring Boot 方式
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mybatisPlusInterceptor;
}
}
使用
@RequestMapping("/sel")
public Object sel(Long p){
Page<Book> page1 = new Page<>(p,5);
Page<Book> res = iBookService.page(page1);
return res.getRecords();
}
第二页的数据
用QueryWrapper带条件查询分页
@RequestMapping("/sel")
public Object sel(Long p,String name){
QueryWrapper<Book> wrapper = new QueryWrapper<>();
wrapper.like(StringUtils.isNotEmpty(name),"bookname",name);
Page<Book> page1 = new Page<>(p,5);
Page<Book> res = iBookService.page(page1,wrapper);
return res.getRecords();
}
总结
通过本篇博客的学习,读者深入了解了逻辑删除、乐观锁和分页插件这三个高级数据库操作技术。逻辑删除为数据的保留和恢复提供了便捷的方式,乐观锁解决了高并发场景下的数据一致性问题,而分页插件使得处理大数据集合更为高效。在实际项目中,灵活运用这些技术将使系统更加稳健、高效。