JPA 与 MyBatis 如何选型?两者的核心区别是什么?
结论先行:JPA(Spring Data JPA)是 ORM 思路——以实体对象为中心,框架自动生成 SQL,开发效率高但复杂 SQL 难优化;MyBatis 是 SQL 优先思路——SQL 由你写全、结果映射由框架做,复杂查询可控性强但样板代码多。选型看团队与业务:CRUD 密集、模型清晰选 JPA;报表/复杂 SQL/存量库强管控选 MyBatis。
一、核心差异对比
| 维度 | Spring Data JPA | MyBatis |
|---|---|---|
| 编程模型 | 实体 + 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。