Mybatis-plus
📖 官方文档
🌐文档
☄️特性
- 润物无声:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑。
- 效率至上:只需简单配置,即可快速进行单表 CRUD 操作,从而节省大量时间。
- 丰富功能:代码生成、物理分页、性能分析等功能一应俱全。
⛓结构

➕ 添加依赖
1 | <parent> |
💥配置文件
1 | # Server |
🌀主键生成策略
❄️Snowflake
SnowFlake
是Twitter
开源的分布式ID
生成算法。
🆔ID结构
SnowFlake
生成ID
固定是一个long
型的数字,一个long
型占8个字节,也就是64个bit
,分配如下:

- 第一个bit是标识位部分,在
Java
中由于long
的最高位是符号位,正数是0
,负数是1
,一般生成的ID
为正数,所以固定为0
。 - 时间戳部分占
41bit
,这个是毫秒级的时间,一般实现上不会存储当前的时间戳,而是时间戳的差值(当前时间-固定的开始时间),这样可以使产生的ID
从更小值开始。41
位的时间戳可以使用69
年。 - 工作机器
ID
占10bit
,这里比较灵活,比如,可以使用前5
位作为数据中心机房标识,后5
位作为单机房机器标识,可以部署1024
个节点。 - 序列号部分占
12bit
,支持同一毫秒内同一个节点可以生成2^12^=4096
个ID
。
🌠 优点和缺点
优点:
- 毫秒数在高位,自增序列在低位,
ID
趋势递增。 - 以服务方式部署,可以做高可用。
- 根据业务分配
bit
位,灵活。
缺点:
- 每台机器的时钟不同,当时钟回拨可能会发生重复ID。
- 当数据量大时,需要对
ID
取模分库分表,在跨毫秒时,序列号总是归0
,会发生取模后分布不均衡。
💻 Java实现
1 | package top.parak.common; |
🔱在Mybatis-plus中自定义ID生成器
1 |
|
🚀 CRUD拓展
建表
1 | CREATE TABLE `user` ( |
实体
1 |
|
🌌自动填充
对于普通字段
1 | public enum FieldFill { |
所有的数据库表都应该包含创建时间gmt_create和修改时间gmt_modified,而且需要自动化。——《阿里巴巴开发手册》
🛢数据库级别
1 | ALTER TABLE user ADD update_time DATETIME DEFAULT CURRENT_TIMESTAMP; |
⌨️代码级别
- 数据表添加字段
1 | ALTER TABLE user ADD update_time DATETIME; |
- 实体类添加字段和注解
1 |
|
- 编写处理器处理注解
1 | package top.parak.handler; |
🔏悲观锁
📖理解
当要对数据库的一条数据进行修改的时候,为了避免同时被其他人修改,最好的办法就是直接对数据进行加锁防止并发。
这种借助数据库锁机制,在修改数据之前先锁定,再修改的方式被称为悲观并发控制(Pessimistic Concurrency Control,缩写PCC,又名悲观锁)。
💠实现
悲观锁的实现,往往依靠数据库提供的锁机制(只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。悲观锁的实现:
- 传统的关系型数据库使用这种锁机制,比如行锁、表锁、读锁、写锁等,都是在做操作之前先上锁
- Java里面的同步
synchronized
关键字的实现 JUC
中的lock
加锁
🔱分类
- 共享锁:又称为读锁,简称S锁。顾名思义,共享锁就是多个事务对于同一个数九可以共享一把锁,都能访问到数据,但是只能读不能修改。
- 排他锁:又称为写锁,简称X锁。顾名思义,排他锁就是不能与其他锁并存,如果一个事务获取了一个数据行的排它锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取到排他锁的事务可以对数据进行读取和修改。
💬说明
悲观并发控制实质上是先取锁再访问的保守策略,为数据处理的安全提供了保证。
但是在效率方面,处理加锁的机制会让数据库产生额外的开销,还有增加产生死锁的机会。
另外还会降低并行性,一个事务如果锁定了某行数据,其他事务就必须等待该事务处理完才可以处理那行数据。
🔓乐观锁
📖理解
乐观锁假设数据在一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则返回给用户错误的信息,让用户决定如何去做。乐观锁适用于读操作多的场景,这样可以提高程序的吞吐量。
💠实现
乐观锁不会可以使用数据库本身的锁机制,而是依据数据本身来保证数据的正确性。乐观锁的实现:
CAS实现:
Java
中java.concurrent.atomic
包下面的原子变量使用了乐观锁的一种CAS
实现方式版本号控制:一般是在数据表中添加一个数据版本号
version
字段,表示数据被修改的次数。当数据被修改时,version
值会+1。当线程A更新数据值时,在读取数据的同时也会读取version
值,在提交更新时,若刚才读取到version
值与当前数据库中的version
值相等时才更新,否则重试更新操作,直到更新成功。1
2
3
4-- 1 查询版本号
select version as oldversion where id = #{id}
-- 2 更新操作
update set ... , version = version + 1 where id = #{id} and version = oldversion
💬说明
乐观并发控制相信事务之间的数据竞争概率是比较小的。因此尽可能直接做下去,直到提交的时候才去锁定,所以不会产生任何锁或死锁。
🔧插件
- 数据表添加字段
1 | ALTER TABLE user ADD version INT DEFAULT 1; |
- 实体类添加属性和注解
1 | /* 乐观锁 */ |
- 在mybatis-plus配置类中增加乐观锁拦截器
1 |
|
- 乐观锁测试
1 | /** |
1 | # 测试结果 |
🔖分页查询
- mybatis-plus配置类中增加分页拦截器
1 |
|
- 直接使用
Page
对象
1 | /** |
1 | # 测试结果 |
📛逻辑删除
物理删除:从数据库中直接删除。
逻辑删除:不从数据库中移除,通过一个变量使其失效。实质上是更新,防止数据丢失。
- 数据库添加字段
1 | ALTER TABLE user ADD deleted |
- 实体类添加属性和注解
1 | /* 逻辑删除 */ |
- Application.properties中增加配置
1 | # 逻辑删除 |
🔍性能分析
3.4.X版本中该插件已经移除。
💤条件构造器

1 |
|
🔰代码生成器
自动生成 entity、mapper、service、controller层的代码
1 | package top.parak.generator; |