MyBatisPlus
介绍:
基于mybatis的升级,两者是合作关系效率更高,可以做到引入不对mb起冲突,可以快速实现单表的CRUD。
MP的使用文档:https://baomidou.com
使用 MybatisPlus 的基本步骤:
① 引入 MybatisPlus 依赖,代替 Mybatis 依赖
1 | <dependency> |
② 定义 Mapper 接口并继承 BaseMapper
1 | public interface UserMapper extends BaseMapper<User> { |
③ 在实体类上添加注解声明表信息
④ 在application.yml中根据需要添加配置
常用注解:
通过扫描实体类基于反射获取实体类信息作为数据库信息
- 约定大于配置
- 类名驼峰转下划线作为表名
- 变量名驼峰转下划线作为字段名
注解:
- @TableName 指定表名
- @Tableld 指定主键 还可以指定Type属性:AUTO数据库自增长 INPUT自己输入 ASSIG_ID采用雪花算法生成id一个long类型的20位数据
- @TableField 指定字段名
使用@TableField的常见场景:
- 成员变量名与数据库字段名不一致
- 成员变量名以is开头,且是布尔值
- 成员变量名与数据库关键字冲突
- 成员变量不是数据库字段 这时候需要属性名为:exist = bollean
示例:
1 |
|
常用配置
示例:
1 | mybatis-plus: |
核心功能:
条件构造器:
用途用来构造where语句
总结:
条件构造器的用法:
- QueryWrapper和LambdaQueryWrapper通常用来构建select、delete、update的where条件部分
- UpdateWrapper和LambdaUpdateWrapper通常只有在set语句比较特殊才使用
- 尽量使用LambdaQueryWrapper和LambdaUpdateWrapper,避免硬编码
案例:
基于Querywrapper的更新和查询
更新名为jack的用户余额为200
1 | void testUpdateByQueryWrapper() { |
基于Updatewrapper的更新
更新id为1,2,4的用户,余额减少200
1 | void testUpdateWrapper() { |
基于lambda的更新,(防止硬编码)推荐!
查询id,username,信息,工资,当员工姓名有o并且工资等于1000
1 | void testLambdaQueryWrapper() { |
自定义SQL
用处:
- 为了防止sql语句基本写在业务层中导致mapper层无用
- 可以利用MP的wrapper来构造复杂的where条件,然后自己定义SQL语句剩下的部分
代码示例:
① 基于 Wrapper 构建 where 条件
1 | List<Long> ids = List.of(1L, 2L, 4L); |
② 在 mapper 方法参数中用 Param 注解声明 wrapper 变量名称,必须是 ew
1 | void updateBalanceByIds( LambdaQueryWrapper<User> wrapper, int amount); |
③ 自定义 SQL,并使用 Wrapper 条件
1 | <update id="updateBalanceByIds"> |
Service接口
使用流程:
- 自定义Service接口继承IService接口
1 | public interface IUserService |
- 自定义Service实现类,实现自定义接口并继承ServiceImpl类
1 | public class UserServiceImpl |
IService (Interface)
- getOne(Wrapper)
- saveBatch(List)
UserService (Interface)
- listByName(String)
ServiceImpl (Class)
- getOne(Wrapper)
- saveBatch(List)
UserServiceImpl (Class)
- listByName(String)
关系说明(基于图示箭头)
- UserService 继承/扩展了 IService。
- ServiceImpl 实现了 IService 接口。
- UserServiceImpl 继承了 ServiceImpl 类。
- UserServiceImpl 实现了 UserService 接口。
实现复杂业务接口
在一些需要先提前校验的时候,我们需要先写好判断条件,再基于mp的CRUD功能进行对数据的修改
IService的Lambd的实现方法
用来构造复杂查询
案例:
需求: 实现一个根据复杂条件查询用户的接口,查询条件如下:
- name: 用户名关键字,可以为空
- status: 用户状态,可以为空
- minBalance: 最小余额,可以为空
- maxBalance: 最大余额,可以为空
1 | <select id="queryUsers" resultType="com.itheima.mp.domain.po.User"> |
该代码是一个 MyBatis 的动态 SQL 查询语句,用于根据条件动态构建 SELECT 语句。
1 | public List<User> queryUsers(String name, Integer status, Integer minBalance, Integer maxBalance) { |
该代码使用了 MyBatis-Plus 的 LambdaQueryWrapper(通过 lambdaQuery() 获取),实现了动态 SQL 查询逻辑,与上一张图片中的 XML 写法功能等价。
批处理:
IService批量新增
需求:批量插入10万条用户数据,并作出对比:
- 普通for循环插入
- IService的批量插入
- 开启rewriteBatchedStatements=true参数
批处理方案:
- 普通for循环逐条插入速度极差,不推荐
- MP的批量新增,基于预编译的批处理,性能不错
- 配置jdbc参数,开rewriteBatchedStatements,性能最好
代码:
1 | void testSaveBatch() { |
拓展功能
代码生成器:
用来快速构建一个控制层,业务层,实体类,持久层的开发框架,让用户不需要进行重复性构造框架
DB静态工具:
1 | public UserVO queryUserAndAddressById(Long id) { |
该代码展示了如何根据 ID 查询用户及其关联的地址信息,并将实体对象(PO)转换为视图对象(VO)返回。其中使用了 Db.lambdaQuery 进行关联表查询,以及 Hutool 工具包中的 BeanUtil 和 CollUtil 进行对象属性拷贝和集合判空处理。
逻辑删除:
逻辑删除就是基于代码逻辑模拟删除效果,但并不会真正删除数据。思路如下:
- 在表中添加一个字段标记数据是否被删除
- 当删除数据时把标记置为 1
- 查询时只查询标记为 0 的数据
例如逻辑删除字段为 deleted:
- 删除操作:
1 | UPDATE user SET deleted = 1 WHERE id = 1 AND deleted = 0 |
- 查询操作:
1 | SELECT * FROM user WHERE deleted = 0 |
MybatisPlus 提供了逻辑删除功能,无需改变方法调用的方式,而是在底层帮我们自动修改 CRUD 的语句。我们要做的就是在 application.yaml 文件中配置逻辑删除的字段名称和值即可:
1 | mybatis-plus: |
注意 逻辑删除本身也有自己的问题,比如:
- 会导致数据库表垃圾数据越来越多,影响查询效率
- SQL 中全都需要对逻辑删除字段做判断,影响查询效率
因此,不太推荐采用逻辑删除功能,如果数据不能删除,可以采用把数据迁移到其它表的办法。
枚举处理器:
使用方法:
在 application.yml 中配置全局枚举处理器:
1 | mybatis-plus: |
配置用于指定 MyBatis-Plus 处理枚举类型的默认策略,这里使用了 MP 自带的 MybatisEnumTypeHandler。
插件功能
分页插件
感觉还是pageHelper好用啊!!!!
分页插件
首先,要在配置类中注册 MyBatisPlus 的核心插件,同时添加分页插件:
1 |
|
这段代码展示了如何在 Spring Boot 项目中通过 Java 配置类来注册 MyBatis-Plus 的分页拦截器。
接着,就可以使用分页的 API 了:
1 |
|
这段代码展示了如何使用 MyBatis-Plus 提供的 Page 对象进行分页查询、设置排序规则以及获取分页结果(如总记录数、总页数和当前页的数据列表)。