JPA 与 MyBatis 如何选型?两者的核心区别是什么?

结论先行:JPA(Spring Data JPA)是 ORM 思路——以实体对象为中心,框架自动生成 SQL,开发效率高但复杂 SQL 难优化;MyBatis 是 SQL 优先思路——SQL 由你写全、结果映射由框架做,复杂查询可控性强但样板代码多。选型看团队与业务:CRUD 密集、模型清晰选 JPA;报表/复杂 SQL/存量库强管控选 MyBatis。

一、核心差异对比

维度Spring Data JPAMyBatis
编程模型实体 + Repository 接口Mapper 接口 + XML/SQL
SQL 生成框架自动(JPQL/HQL)开发者手写
复杂查询JPQL/原生 SQL,难调优SQL 全可控,易优化
学习曲线ORM 概念多SQL 熟练即可上手
对象关系强(关联、级联、生命周期)弱(手写映射)
动态 SQL需 Specification/QueryDSL<if>/<where>/<foreach> 天然支持
缓存一级缓存 + 可配二级一级 + 可配二级
迁移适配换库需注意方言SQL 与库绑定需改写

二、典型写法对照

// JPA:声明即用
public interface OrderRepository extends JpaRepository<Order, Long> {
    List<Order> findByStatusAndUserId(String status, Long userId);
}
<!-- MyBatis:SQL 在手 -->
<select id="listByStatus" resultType="Order">
  SELECT * FROM t_order WHERE status = #{status}
</select>

三、选型建议

  • 团队 ORM 熟练、领域模型复杂、希望少写 SQL:JPA;
  • 金融/报表/大数据量分页、SQL 性能敏感、库结构由 DBA 强管控:MyBatis;
  • 规避 N+1:JPA 用 fetch join / @EntityGraph 或批量抓取,MyBatis 用嵌套 resultMap/分步查询控制;
  • 混合使用可行但成本高,先在工程边界上隔离(如读模型走 MyBatis、写模型走 JPA),不要在同一方法内混用事务边界不清。

常见追问 / 记忆点

  • 追问:JPA 的 N+1 问题是怎么产生的?答:懒加载关联集合逐条查询产生 N+1,用 @EntityGraph/join fetch 一次取出。
  • 追问:为什么很多老项目选 MyBatis?答:SQL 可见可控、贴近 DBA 审查习惯,动态 SQL 覆盖复杂查询场景。
  • 记忆点:JPA 面向对象自动 SQL、MyBatis 面向 SQL 手动映射;复杂可控选 MyBatis,模型驱动选 JPA。
笔记加载中…