MyBatis 和 Hibernate 有什么区别?

#Java#面试八股

MyBatis 和 Hibernate 有什么区别?

结论先行:Hibernate 是全自动 ORM,把「表」映射成「对象」,SQL 由框架生成;MyBatis 是半自动映射框架,把「SQL」映射成「对象」,SQL 由开发者掌控。要极致可控的 SQL 与性能调优选 MyBatis,要快速开发、跨数据库移植选 Hibernate(今天更常见的是 Spring Data JPA)。

1. 两者的定位差异

Hibernate:  Java 对象  ──框架生成 SQL──▶  数据库
             (你写 HQL / 操作实体,SQL 不可见)

MyBatis:    你写 SQL  ──框架做参数与结果映射──▶  数据库
             (SQL 可见、可调、可移植性弱)

一个直观的区别:分页查询时,Hibernate 由方言(Dialect)拼 limit,换数据库不用改代码;MyBatis 里 limit 是你自己写的,换 Oracle 就得改成 rownum。

2. 关键维度对比

维度MyBatisHibernate / JPA
映射方式SQL 与对象映射(XML/注解)实体与表映射(ORM)
SQL 控制力完全掌控,可写任意 SQL由框架生成,调优需懂 HQL/Criteria
学习曲线会 SQL 就能上手需理解一级/二级缓存、脏检查、延迟加载
数据库移植弱,SQL 方言自己处理强,靠 Dialect 适配
动态 SQL<if>、<foreach> 原生支持需 Criteria API 或 Specification
性能调优改 SQL、加索引,直观关注 N+1、抓取策略、批量写入
缓存一级/二级缓存,粒度粗一级/二级缓存 + 查询缓存
适合场景互联网高并发、复杂报表 SQL业务模型稳定、以 CRUD 为主的中后台

3. 同一需求的两种写法

MyBatis:SQL 与映射显式声明。

<select id="selectByStatus" resultType="com.example.Order">
    SELECT id, user_id, amount, status
    FROM t_order
    WHERE status = #{status}
      AND created_at &gt;= #{begin}
    ORDER BY id DESC
    LIMIT #{offset}, #{size}
</select>

Hibernate / JPA:只描述查询意图,SQL 由框架生成。

public interface OrderRepository extends JpaRepository<Order, Long> {

    // 方法名即查询语义,框架生成 SQL
    List<Order> findByStatusAndCreatedAtAfterOrderByIdDesc(
            OrderStatus status, LocalDateTime begin, Pageable pageable);
}

如果这条 SQL 需要用到 FORCE INDEX、窗口函数或复杂的多表聚合,JPA 就得退化到 @Query(nativeQuery = true),此时它相对 MyBatis 的优势基本消失。

4. 怎么选

  • 团队 SQL 能力强、查询复杂、性能敏感:选 MyBatis,SQL 全部可审查、可 explain。
  • 领域模型复杂、实体关系多、以增删改查为主:选 JPA,省掉大量样板映射。
  • 已经用了 Spring Data JPA,但个别复杂查询:用 @Query 或 MyBatis 混用,不必二选一。
  • 不要因为「MyBatis 更火」就选它:MyBatis 把复杂度转移给了 SQL 和 XML 维护。

5. 常见追问

追问一:MyBatis 算 ORM 吗? 严格说不算。ORM 的核心是对象与表的自动映射、状态跟踪与脏检查;MyBatis 只做「SQL 结果 → 对象」的映射,不跟踪对象状态,所以被称为 SQL Mapper 或半自动 ORM。

追问二:Hibernate 的一级缓存和 MyBatis 的一级缓存一样吗? 都是 Session/SqlSession 级别,但 Hibernate 的一级缓存同时承担「持久化上下文」职责,能感知对象修改并在 flush 时自动发 UPDATE;MyBatis 的缓存只是查询结果缓存,改对象不会自动落库。

追问三:MyBatis 为什么在互联网公司更流行? 互联网业务 SQL 复杂且变化快,DBA 要求所有 SQL 可审计、可加 hint;MyBatis 的 SQL 明文写在 XML 里,评审、慢查询定位、索引优化都直接。JPA 生成的 SQL 不透明,线上出问题排查成本高。

追问四:用了 JPA 还能不能写原生 SQL? 可以,@Query(value = "...", nativeQuery = true) 或 EntityManager.createNativeQuery。但一旦大量使用原生 SQL,JPA 的移植性优势就没了,等于用 JPA 的壳写 MyBatis 的活。

小结

区别的本质是控制权放在谁手里:Hibernate 把 SQL 交给框架,换来开发效率与移植性;MyBatis 把 SQL 交回开发者,换来可控性与调优空间。选型看的是团队能力与业务查询复杂度,而不是框架本身的「先进程度」。

笔记加载中…