Mybatis-plus
快速入门
导入
mybatis-plus依赖中含有mybatis依赖 所以直接更换依赖即可 导入mybatis依赖
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.3</version></dependency>
定义mapper接口继承BaseMapper
常见注解
MyBatisPlus通过扫描实体类 并且基于反射得到实体类信息作为数据库表信息 而且有以下约定
- 类名驼峰转下划线作为表名
- 名为id字段作为主键
- 变量名驼峰转下划线作为表字段名
MyBatis中有三个常见注解
@TableName
来指定表名@TableId
来指定表中主键- value是主键名
- type是主键的增长策略 AUTO是自增长
INPUT
通过set方法注入ASSIGN_ID
通过雪花算法来生成id 默认雪花算法生成Long型id
@TableField
来指定普通字段名 且常见场景如下- 变量名和数据库名不一致
- 变量名以is开头 且是布尔值
- 变量名和数据库关键字冲突 比如order和order by就冲突了
- 变量名不是数据库字段 需要使用转义字符

常用配置
MyBatisPlus继承了mybatis的基础配置和一些特有配置
mybatis-plus:type-aliases-package: com.itheima.mp.domain.po # 别名扫描包mapper-locations: "classpath*:/mapper/**/*.xml" # Mapper.xml文件地址,默认值configuration:map-underscore-to-camel-case: true # 是否开启下划线和驼峰的映射cache-enabled: false # 是否开启二级缓存global-config:db-config:id-type: assign_id # id为雪花算法生成update-strategy: not_null # 更新策略:只更新非空字段
核心功能
条件构造器
MyBatisPlus支持各种复杂where条件 都是通过Wrapper来构造的
条件构造器的用法
- QueryWrapper和LambdaQueryWrapper通常来构建select delete update的where条件部分
- UpdateWrapper和LambdaUpdateWrapper通常只有在set语句比较特殊才使用
- 尽量使用LambdaQueryWrapper和LambdaUpdateWrapper 避免硬编码
自定义sql
Where条件用mp来写 剩余部分用xml自定义来写 从而组装完整的sql语句 分为以下步骤
- 基于Wrapper构建where条件
- 在mapper方法中调用@Param注解指定wrapper名称 必须是ew
- 自定义sql 构建完整语句
Service接口
要需要实现分两步
- 自定义接口继承IService接口 从而自定义接口有所有方法声明
public interface IUserService extends IService<User>
- 实现类继承IServiceImpl实现类 从而实现类有所有方法实现
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService
IService开发基础功能接口
首先注意的是注入的时候用构造函数来注入 可以使用lombok来注入 在类上使用@RequiredAgrsConstructor
来通过注入 在类中直接@private final IUserService userService
即可
- 可以解决循环依赖的问题 循环依赖直接抛异常
- 在测试方法里也更好用 直接用构造函数即可 而autowired还需要反射
- 不可变性 用final定义保证变量不会被修改
使用lambdaUpdate的时候 构建完sql语句记得跟上.update()
这个才是真正执行update语句 上面全都是构建sql语句
lambdaUpdate().set(User::getBalance, remain).set(remain < 0,User::getStatus,2).eq(User::getId,id).eq(User::getBalance,user.getBalance()).update();
批量处理
- 普通for循环插入
速度极差 - IService批量插入
使用批处理的时候采用的是预编译 比如十万条数据 每一千条发送一个sql 默认是发送一千条sql 但是这样性能还是会很慢 - 开启rewriteBatchedStatements=true参数
可以将一千条sql拼成一条sql语句 性能最好
在配置文件里jdbc的配置中spring: datasource: url: jdbc:mysql://127.0.0.1:3306/mp?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
后面拼上&rewriteBatchedStatements=true
就可以实现拼接sql了
扩展功能
Db静态工具
方便解决循环依赖的问题
比如需求是 根据id查询用户 查询用户的同时查询用户对应地址和根据用户id查询收货地址 并且验证用户状态
这两个需求分别需要在UserService中注入AddressService和在AddressService中注入UserService 也就是循环依赖 因此发生问题 如果采用@Autuwired注入 编译器不会报错 如果是定义静态常量用构造器注入 编译器会报循环依赖的错误
但是springboot不是解决循环依赖了吗 通过三级缓存?
解决该问题就是用Db静态工具 不需要再注入其他的Service 只需要传一个字节码文件 通过反射 就可以实现sql语句查询List<Address> addresses = Db.lambdaQuery(Address.class).eq(Address::getUserId, id).list();
逻辑删除
也就是当购物订单用户想要删除的时候 在用户端显示删除了该数据 但是商家端不会删除 因此采用的策略就是逻辑删除 思路如下
- 在表中添加一个字段标记数据是否被删除
- 当删除数据时把标记修改为1
- 查询时只查询数据为0的
mybatis-plus对逻辑删除做了适配 只需要在yaml文件中配置即可
但是同样的 逻辑删除存在一些问题
- 会导致数据库垃圾数据越来越多 影响查询效率
- sql中全部都需要对逻辑字段进行判断 影响查询效率
还有一种方法是新开一张表 采用数据迁移的方式来
枚举处理器

当数据库中和PO中出现要从枚举类型转成其他类型时 就可以通过@EnumValue
来明确枚举中的变量哪一个跟数据库字段是对应的
然后在配置文件中配置
JSON处理器
在表中有json字段的属性info 而在idea中是用string来接收的 mp会自动进行转换 但是如果定义一个info对象来接收 就做不到了 因此需要进行配置
- 用@TableField标记开启json处理
- 因为对象中嵌套了另一个对象 因此需要在表名的
@TableName
开启自动ResultMap封装处理

插件功能
分页插件
使用分页插件首先需要在配置类里注册分页插件 mp的插件是基于拦截器实现的 会在所有业务到达数据库之前拦截然后实现相关功能
然后Page<User> page = Page.of(pageNo,pageSize);
就可以直接使用了 通过静态方法传参 得到page对象 还可以通过add.Order来对该对象进行排序 调用service的page方法查询
返回的对象其实和定义的page对象是同一个对象 然后里面有各种信息 total总条数 pages总页数 records数据