MyBatisPlus
定义
mybatis-plus是一款Mybatis增强工具,用于简化开发,提高效率。
核心功能
注解
-
@TableName
注解在类上,指定类和数据库表的映射关系。实体类的类名(转成小写后)和数据库表名相同时,可以不指定该注解。
-
@TableId
注解在实体类的某一字段上,表示这个字段对应数据库表的主键。
-
@TableField
注解在某一字段上,指定Java实体类的字段和数据库表的列的映射关系。
-
@Version
乐观锁注解
-
@EnumValue
注解在枚举字段上
-
@TableLogic
逻辑删除
-
KeySequence
序列主键策略
-
InterceptorIgnore
插件过滤规则
CRUD接口
mp封装了一些最基础的CRUD方法,只需要直接继承mp提供的接口,无需编写任何SQL,即可食用。mp提供了两套接口,分别是Mapper CRUD接口和Service CRUD接口。并且mp还提供了条件构造器Wrapper,可以方便地组装SQL语句中的WHERE条件
Mapper CRUD
只需定义好实体类,然后创建一个接口,继承mp提供的BaseMapper,即可食用。mp会在mybatis启动时,自动解析实体类和表的映射关系,并注入带有通用CRUD方法的mapper。
Service CRUD
另外一套CRUD是Service层的,只需要编写一个接口,继承IService,并创建一个接口实现类,即可食用。(这个接口提供的CRUD方法,和Mapper接口提供的功能大同小异,比较明显的区别在于IService支持了更多的批量化操作,如saveBatch,saveOrUpdateBatch等方法。
使用方法
- 首先,新建一个接口,继承IService
- 创建这个接口的实现类,并继承ServiceImpl,最后打上@Service注解,注册到Spring容器中,即可食用
- @Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { }
条件构造器
而QueryWrapper针对SELECT语句,提供了select()方法,可自定义需要查询的列,而UpdateWrapper针对UPDATE语句,提供了set()方法,用于构造set语句。
Condition 条件构造器的诸多方法中,均可以指定一个boolean类型的参数condition,用来决定该条件是否加入最后生成的WHERE语句中
自定义SQL
条件构造器
注解上编写sql语句
分页查询
AR模式
定义
ActiveRecord模式,通过操作实体对象,直接操作数据库表。
使用过程
- 让实体类User继承自Model
public class User extends Model<User>
- 直接调用实体对象上的方法
boolean success = user.insert(); // 插入
主键策略
定义
在定义实体类时,用@TableId指定主键,而其type属性,可以指定主键策略。
种类
-
AUTO
数据库ID自增,依赖于数据库。在插入操作生成SQL语句时,不会插入主键这一列
-
NONE
未设置主键类型。若在代码中没有手动设置主键,则会根据主键的全局策略自动生成(默认的主键全局策略是基于雪花算法的自增ID)
-
INPUT
需要手动设置主键,若不设置。插入操作生成SQL语句时,主键这一列的值会是null。
-
ASSIGN_ID
当没有手动设置主键,即实体类中的主键属性为空时,才会自动填充,使用雪花算法
-
ASSIGN_UUID
当实体类的主键属性为空时,才会自动填充,使用UUID
逻辑删除
定义
逻辑删除是为了方便数据恢复,和保护数据本身价值的一种方案。
步骤
application.yml中配置
mybatis-plus:global-config:db-config:logic-delete-field: deleted # 全局逻辑删除的实体字段名logic-delete-value: 1 # 逻辑已删除值(默认为1)logic-not-delete-value: 0 # 逻辑未删除值(默认为0)# 若逻辑已删除和未删除的值和默认值一样,则可以不配置这2项
对sql的影响
- INSERT语句:没有影响
- SELECT语句:追加WHERE条件,过滤掉已删除的数据
- UPDATE语句:追加WHERE条件,防止更新到已删除的数据
- DELETE语句:转变为UPDATE语句
自动填充
定义
mp可以通过配置,对某些字段进行自动填充,例如’新增时间’,‘修改时间’,'操作人’等等
步骤
- 在实体类中的某些字段上,通过@TableField设置自动填充
@TableField(fill = FieldFill.INSERT) // 插入时自动填充private LocalDateTime createTime;@TableField(fill = FieldFill.UPDATE) // 更新时自动填充private LocalDateTime updateTime;
- 实现自动填充处理器
乐观锁插件
定义
当出现并发操作时,需要确保各个用户对数据的操作不产生冲突,此时需要一种并发控制手段。而乐观锁,正如其名,它先假设不存在冲突情况,而在实际进行数据操作时,再检查是否冲突。乐观锁的一种通常实现是版本号,在MySQL中也有名为MVCC的基于版本号的并发事务控制。
适用场景
在读多写少的场景下,乐观锁比较适用,能够减少加锁操作导致的性能开销,提高系统吞吐量。
在写多读少的场景下,悲观锁比较使用,否则会因为乐观锁不断失败重试,反而导致性能下降。
原理
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果oldVersion与数据库中的version不一致,就更新失败
步骤
- 配置乐观锁插件
@Configuration
public class MybatisPlusConfig {/** 3.4.0以后的mp版本,推荐用如下的配置方式 **/@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return interceptor;}
}
-
在实体类中表示版本的字段上添加注解@Version
@Version private Integer version;
-
使用
注意
- 实体类中version字段,类型只支持int,long,Date,Timestamp,LocalDateTime
- 乐观锁插件仅支持updateById(id)与update(entity, wrapper)方法
- 如果使用wrapper,则wrapper不能复用
性能分析插件
该插件会输出SQL语句的执行时间,以便做SQL语句的性能分析和调优。
动态表名SQL解析器
定义
当数据量特别大的时候,我们通常会采用分库分表。这时,可能就会有多张表,其表结构相同,但表名不同。例如order_1,order_2,order_3,查询时,我们可能需要动态设置要查的表名。
步骤
- 配置动态表名拦截器
- 测试
@Testpublic void testDynamicTable() {user2Mapper.selectList(null);}