共220行
2026-02-14 10:56:29
MyBatis-Plus(简称MP)是MyBatis框架的增强工具,旨在通过无侵入式扩展简化数据库操作、提升开发效率,同时保留MyBatis原有的灵活性与SQL控制能力。其核心定位是“做MyBatis做不到的事,不做MyBatis已有的事”,聚焦于解决传统MyBatis开发中重复CRUD编码、动态SQL繁琐、分页逻辑删除等通用功能需手动实现等痛点。
MyBatis-Plus的特性围绕“高效、便捷、安全”设计,覆盖了数据库操作的各个环节:
无侵入式设计:
仅通过依赖引入和接口继承增强功能,不修改MyBatis原有架构与代码。例如,实体类只需继承Model类即可支持ActiveRecord模式,Mapper接口继承BaseMapper即可获得通用CRUD方法,无需修改现有MyBatis配置。
强大的通用CRUD操作:
提供BaseMapper接口(包含selectById、insert、updateById、deleteById等10+个通用方法)和IService/ServiceImpl服务层接口(封装了批量操作、分页查询等复杂逻辑),实现单表90%以上的CRUD操作无需手写SQL。例如:
// Mapper接口继承BaseMapper,直接使用通用方法
public interface UserMapper extends BaseMapper<User> {}
// Service实现类继承ServiceImpl,调用批量删除
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
public void deleteBatch(List<Long> ids) {
baseMapper.deleteBatchIds(ids);
}
}灵活的条件构造器:
提供QueryWrapper(查询条件)、UpdateWrapper(更新条件)、LambdaQueryWrapper(Lambda表达式条件)等工具,通过链式调用构建复杂查询条件,避免手动拼接SQL。例如:
// 查询年龄大于25、姓名包含"张"的用户(Lambda形式,避免字段名写错)
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.gt(User::getAge, 25).like(User::getName, "张");
List<User> users = userMapper.selectList(wrapper);内置实用插件:
PaginationInnerInterceptor后,分页查询等同于普通List查询(如Page<User> page = new Page<>(1, 10); userMapper.selectPage(page, wrapper);),支持MySQL、Oracle等多种数据库。@TableLogic注解标记逻辑删除字段(如deleted),实现“软删除”(而非物理删除),避免数据丢失。@Version注解标记版本字段,解决并发更新问题(如更新时自动检查版本号,避免脏数据)。代码生成器:
通过AutoGenerator自动生成Entity、Mapper、Service、Controller等代码,支持Freemarker、Velocity等模板引擎,减少重复编码工作。例如:
AutoGenerator mpg = new AutoGenerator();
mpg.setDataSource(dataSourceConfig); // 数据源配置
mpg.setPackageInfo(packageConfig); // 包路径配置
mpg.setStrategy(strategyConfig); // 策略配置(如表名前缀、字段命名规则)
mpg.execute(); // 执行生成主键自动生成:
支持4种主键策略(雪花算法、UUID、自增、数据库ID自增),通过@TableId注解配置,解决分布式系统主键唯一性问题。例如:
@Data
public class User {
@TableId(type = IdType.ASSIGN_ID) // 雪花算法生成主键
private Long id;
private String name;
private Integer age;
}MyBatis-Plus与MyBatis的关系是“补充与增强”,而非“替代”。两者的核心差异如下:
| 维度 | MyBatis | MyBatis-Plus |
|---|---|---|
| CRUD操作 | 需手动编写SQL语句(XML或注解) | 通用Mapper/Service提供90%以上通用CRUD方法 |
| 动态SQL | 需手动拼接<if>、<foreach>等标签 |
条件构造器通过链式调用简化动态SQL |
| 分页功能 | 需手动编写LIMIT语句或集成第三方插件 |
内置分页插件,配置后直接使用 |
| 逻辑删除 | 需手动添加deleted字段判断 |
@TableLogic注解实现软删除 |
| 代码生成 | 需手动编写或使用第三方工具 | 内置代码生成器,快速生成全栈代码 |
MyBatis-Plus适用于需要快速交付、减少重复编码的项目,尤其适合以下场景:
MyBatis-Plus通过无侵入式增强,将MyBatis从“需要手动编写大量SQL”的工具,转变为“聚焦业务逻辑”的框架。其核心价值在于:
总之,MyBatis-Plus是Java持久层框架的“效率倍增器”,尤其适合需要快速开发、注重代码可维护性的项目。对于熟悉MyBatis的开发者来说,MyBatis-Plus是“必须掌握的工具”;对于新手来说,MyBatis-Plus的“开箱即用”特性可快速入门持久层开发。
| 维度 | MyBatis-Plus | JPA(Java Persistence API) |
|---|---|---|
| 定位 | MyBatis 的增强工具,聚焦简化单表 CRUD 操作,保留原生 SQL 能力 | Java EE 标准 ORM 规范,强调面向对象映射,支持复杂查询和事务管理 |
| 设计理念 | “约定优于配置”,通过通用方法减少重复代码,适合快速开发 | “标准化与抽象化”,通过注解和接口实现对象-关系映射,适合复杂业务模型 |
| 灵活性 | 高,支持自定义 SQL 和插件扩展 | 中等,依赖框架生成 SQL,复杂查询需结合 Criteria API 或原生 JPQL |
| 学习曲线 | 平缓,熟悉 MyBatis 后易上手 | 陡峭,需掌握实体状态、级联、懒加载等概念 |
MyBatis-Plus
继承 BaseMapper 即可自动获得全量 CRUD 方法,无需编写 SQL:
public interface UserMapper extends BaseMapper<User> {}
// 直接调用内置方法
userMapper.insert(user);JPA
通过继承 JpaRepository 实现基础操作,方法名解析生成 SQL:
public interface UserRepository extends JpaRepository<User, Long> {}
// 方法名自动生成查询(如 findByName)
userRepository.findByName("John");MyBatis-Plus
使用 QueryWrapper 或 LambdaQueryWrapper 链式构建条件:
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.gt("age", 20).like("name", "张");
userMapper.selectList(wrapper);JPA
依赖 @Query 注解或 Specification 动态拼接:
@Query("SELECT u FROM User u WHERE u.age > :age AND u.name LIKE %:name%")
List<User> findByAgeAndName(@Param("age") int age, @Param("name") String name);MyBatis-Plus
内置分页插件,配置简单且性能透明:
Page<User> page = new Page<>(1, 10);
IPage<User> result = userMapper.selectPage(page, null);JPA
需结合 Pageable 接口,分页逻辑由框架处理:
Pageable pageable = PageRequest.of(0, 10);
Page<User> result = userRepository.findAll(pageable);MyBatis-Plus
适合简单联表查询,复杂场景需手动编写 XML 或注解 SQL:
<!-- MyBatis-Plus XML -->
<select id="selectWithOrders" resultType="User">
SELECT * FROM user u LEFT JOIN order o ON u.id = o.user_id
</select>JPA
支持 JPQL 和 Criteria API,适合多表关联与动态查询:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<User> query = cb.createQuery(User.class);
Root<User> root = query.from(User.class);
Join<User, Order> orders = root.join("orders", JoinType.LEFT);
query.select(root).where(cb.gt(root.get("age"), 20));| 场景 | MyBatis-Plus | JPA |
|---|---|---|
| 单表 CRUD | 极快,无额外抽象层 | 较慢,需处理 ORM 映射与缓存 |
| 复杂查询 | 需手动优化 SQL,灵活性高 | 自动生成 SQL 可能低效,需手动调优(如 @Query 指定原生语句) |
| 批量操作 | 支持批量插入,但性能弱于原生 MyBatis | saveAll() 默认逐条插入,需配置批量模式 |
| 缓存机制 | 一级缓存(Session 级别),无二级缓存 | 一级缓存(持久化上下文)+ 二级缓存(需配置 Ehcache 等) |
JpaRepository 快速实现 80% 的 CRUD。| 维度 | MyBatis-Plus | JPA |
|---|---|---|
| 优势 | 灵活、高效、学习成本低 | 标准化、功能丰富、适合复杂模型 |
| 劣势 | 复杂查询支持弱、批量性能一般 | 自动生成 SQL 效率低、学习曲线陡峭 |
| 典型用户 | 互联网项目、快速迭代团队 | 企业级系统、传统金融/ERP 项目 |
| 未来趋势 | 在微服务与云原生中持续优化 | 作为 Java 持久化标准长期存在 |
实际建议: