MyBatis-Plus详解(速成版)
一、介绍MyBatis-Plus:1.概念MyBatis-Plus 是一个MyBatis的增强工具在 MyBatis 的基础上只做增强不做改变为简化开发、提高效率而生。MyBatis-Plus的官网简介https://baomidou.com/introduce/2.特点无侵入只做增强不做改变引入它不会对现有工程产生影响如丝般顺滑损耗小启动即会自动注入基本 CURD性能基本无损耗直接面向对象操作强大的 CRUD 操作内置通用 Mapper、通用 Service仅仅通过少量配置即可实现单表大部分 CRUD 操作更有强大的条件构造器满足各类使用需求支持 Lambda 形式调用通过 Lambda 表达式方便的编写各类查询条件无需再担心字段写错支持主键自动生成支持多达 4 种主键策略内含分布式唯一 ID 生成器 - Sequence可自由配置完美解决主键问题支持 ActiveRecord 模式支持 ActiveRecord 形式调用实体类只需继承 Model 类即可进行强大的 CRUD 操作支持自定义全局通用操作支持全局通用方法注入内置代码生成器采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码支持模板引擎更有超多自定义配置等您来使用内置分页插件基于 MyBatis 物理分页开发者无需关心具体操作配置好插件之后写分页等同于普通 List 查询分页插件支持多种数据库支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库内置性能分析插件可输出 SQL 语句以及其执行时间建议开发测试时启用该功能能快速揪出慢查询内置全局拦截插件提供全表 delete 、 update 操作智能分析阻断也可自定义拦截规则预防误操作3.框架结构二、配置MyBatis-Plus:1.引入依赖dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-spring-boot3-starter/artifactId version3.5.15/version /dependency2.使用 MapperScan 注解扫描 mapper 文件SpringBootApplication MapperScan(com.baomidou.mybatisplus.samples.quickstart.mapper) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }3.在 application.yml 文件中增加MyBatis-Plus 的统一配置# mybatis 相关统一配置 mybatis-plus: configuration: #开启下划线转驼峰 map-underscore-to-camel-case: true作用将数据库表中的下划线命名方式映射为 Java 对象中的驼峰命名方式。例如数据库表中的列名为 user_name对应的 Java 对象的属性名为 userName。三、基本使用1. BaseMapper CRUDData TableName(user) public class User { TableId(type IdType.AUTO) private Long id; private String name; private Integer age; private String email; } // Mapper 接口 —— 继承 BaseMapper 即拥有全套单表 CRUD public interface UserMapper extends BaseMapperUser {}增User user new User(); user.setName(张三); user.setAge(25); userMapper.insert(user); // id 自动回填到实体删userMapper.deleteById(1L); userMapper.deleteBatchIds(Arrays.asList(1L, 2L, 3L)); // 条件删除 userMapper.delete(new LambdaQueryWrapperUser() .lt(User::getAge, 18) .eq(User::getName, 张三) );改// 只更新非 null 字段 User user new User(); user.setId(1L); user.setName(李四); userMapper.updateById(user); // 条件更新 userMapper.update(user, new LambdaUpdateWrapperUser() .eq(User::getAge, 25) );查User user userMapper.selectById(1L); ListUser users userMapper.selectBatchIds(Arrays.asList(1L, 2L)); ListUser users userMapper.selectList( new LambdaQueryWrapperUser() .eq(User::getAge, 25) .orderByDesc(User::getCreateTime) ); Long count userMapper.selectCount( new LambdaQueryWrapperUser().gt(User::getAge, 20) );2. 条件构造器 WrapperLambdaQueryWrapper// SELECT * FROM user WHERE age BETWEEN 20 AND 30 // AND name LIKE %张% AND email IS NOT NULL // ORDER BY age DESC, id ASC LIMIT 10 LambdaQueryWrapperUser wrapper new LambdaQueryWrapperUser() .between(User::getAge, 20, 30) .like(User::getName, 张) .isNotNull(User::getEmail) .orderByDesc(User::getAge) .orderByAsc(User::getId) .last(LIMIT 10); ListUser users userMapper.selectList(wrapper);条件方法速查方法说明SQLeq等于name 张三ne不等于name 张三gt/ge大于 / ≥age 18lt/le小于 / ≤age 30between区间age BETWEEN 20 AND 30like/notLike模糊name LIKE %张%likeLeft/likeRight左/右模糊name LIKE %张in/notIn包含id IN (1,2,3)isNull/isNotNull空/非空email IS NULLorderByAsc/orderByDesc排序ORDER BY age ASCUpdateWrapper// UPDATE user SET age 26, name 王五 WHERE id 1 LambdaUpdateWrapperUser wrapper new LambdaUpdateWrapperUser() .eq(User::getId, 1L) .set(User::getAge, 26) .set(User::getName, 王五); userMapper.update(null, wrapper);动态条件// condition 为 false 时该条件不会拼入 SQL LambdaQueryWrapperUser wrapper new LambdaQueryWrapperUser() .eq(StringUtils.isNotBlank(name), User::getName, name) .ge(age ! null, User::getAge, age);嵌套条件// WHERE name 张三 AND (age 20 OR email IS NOT NULL) LambdaQueryWrapperUser wrapper new LambdaQueryWrapperUser() .eq(User::getName, 张三) .and(w - w.eq(User::getAge, 20).or().isNotNull(User::getEmail));3. 分页查询配置插件Configuration public class MybatisPlusConfig { Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); interceptor.addInnerInterceptor( new PaginationInnerInterceptor(DbType.MYSQL) ); return interceptor; } }使用PageUser page new Page(1, 10); // 第1页每页10条 LambdaQueryWrapperUser wrapper new LambdaQueryWrapperUser() .like(StringUtils.isNotBlank(keyword), User::getName, keyword) .orderByDesc(User::getCreateTime); PageUser result userMapper.selectPage(page, wrapper); result.getRecords(); // 当前页数据 result.getTotal(); // 总记录数 result.getPages(); // 总页数联表分页// Mapper 接口 PageUserVO selectUserWithDept(PageUserVO page, Param(ew) LambdaQueryWrapperUser wrapper); // XML // SELECT u.*, d.name AS dept_name // FROM user u LEFT JOIN department d ON u.dept_id d.id // ${ew.customSqlSegment}4. IServiceIService 对 BaseMapper 的进一步封装提供批量操作和链式调用。public interface IUserService extends IServiceUser {} Service public class UserServiceImpl extends ServiceImplUserMapper, User implements IUserService {}常用方法// 增 userService.save(user); userService.saveBatch(userList); // 批量默认每批1000条 // 删 userService.removeById(1L); userService.removeByIds(ids); // 改 userService.updateById(user); userService.updateBatchById(userList); // 批量更新 // 查 userService.getById(1L); userService.list(queryWrapper); userService.count(queryWrapper);链式调用// 链式查询 userService.lambdaQuery() .eq(User::getAge, 25) .like(User::getName, 张) .list(); // 链式更新 userService.lambdaUpdate() .set(User::getAge, 30) .eq(User::getId, 1L) .update(); // 链式删除 userService.lambdaUpdate() .eq(User::getAge, 0) .remove();5. 自动填充实体标注TableField(fill FieldFill.INSERT) private LocalDateTime createTime; TableField(fill FieldFill.INSERT_UPDATE) private LocalDateTime updateTime;实现 HandlerComponent public class MyMetaObjectHandler implements MetaObjectHandler { Override public void insertFill(MetaObject metaObject) { this.strictInsertFill(metaObject, createTime, LocalDateTime::now, LocalDateTime.class); this.strictInsertFill(metaObject, updateTime, LocalDateTime::now, LocalDateTime.class); } Override public void updateFill(MetaObject metaObject) { this.strictUpdateFill(metaObject, updateTime, LocalDateTime::now, LocalDateTime.class); } }四、常用注解速查注解位置说明TableName实体类指定表名TableId主键字段主键策略TableField普通字段映射、填充、非数据库字段TableLogic逻辑删除字段逻辑删除标识Version乐观锁字段配合乐观锁插件EnumValue枚举字段枚举值映射OrderBy字段默认排序IdType 主键策略策略说明AUTO数据库自增INPUT手动设置ASSIGN_ID雪花算法默认LongASSIGN_UUIDUUIDStringTableField 属性TableField(value email_addr) // 列名映射 TableField(exist false) // 非数据库字段 TableField(fill FieldFill.INSERT) // 自动填充 TableField(select false) // 查询不返回五、实用技巧1. 逻辑删除mybatis-plus: global-config: db-config: logic-delete-field: deleted logic-delete-value: 1 logic-not-delete-value: 0配置后所有 CRUD 自动适配deleteById→UPDATE SET deleted1selectList→ 自动追加WHERE deleted0。2. 乐观锁// 配置插件 interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); // 实体 Version private Integer version; // 使用先查后改version 自动 1 User user userMapper.selectById(1L); // version 1 user.setName(新名字); userMapper.updateById(user); // WHERE id1 AND version1 → version23. 防全表更新/删除interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor()); // 阻止无 WHERE 条件的 update/delete4. AR 模式ActiveRecordData TableName(user) public class User extends ModelUser { ... } // 无需注入 Mapper直接用实体操作 User user new User(); user.setName(张三); user.insert(); User found new User(); found.setId(1L); found found.selectById();速记继承 BaseMapper 得单表 CRUDWrapper 构造条件IService 加批量和链式调用分页插件配一行注解搞定映射和填充。