Java 项目包命名中常见 mapper 或 dao,它们有何区别?该选哪个?
引言
在 Java 企业级项目中,mapper 和 dao 都代表数据访问层(持久层),但它们的起源、设计理念和框架绑定有所不同。
简单来说:DAO 是一种通用的设计模式,而 Mapper 是 MyBatis 框架特有的实现方式。
详细对比与分析
| 维度 | DAO (Data Access Object) | Mapper (映射器) |
|---|---|---|
| 本质 | 一种通用设计模式(GOF/JEE模式)。 | MyBatis 框架特有的概念(接口+XML映射)。 |
| 起源 | 早在 EJB 2.x 时代就存在的 Java EE 标准模式。 | MyBatis(原 iBatis)框架引入,用于绑定 SQL。 |
| 核心思想 | 封装对数据源(不仅是数据库,也可以是文件、LDAP等)的访问逻辑,为业务层提供抽象接口。 | 将 Java 接口方法与 SQL 语句(XML/注解)进行映射,让开发者只关心接口,不写实现类。 |
| 典型包名 | dao 或 repository | mapper |
| 典型类名 | UserDAO / UserDao | UserMapper |
| 框架依赖 | 无依赖,任何框架(JDBC、Hibernate、MyBatis)都可以实现 DAO 模式。 | 强依赖 MyBatis,离开 MyBatis 环境毫无意义。 |
| 实现方式 | 早期需要自己写实现类(如 UserDAOImpl 写 JDBC 代码),后来 Spring 可以用模板类或代理。 | 完全不需要写实现类,MyBatis 通过动态代理在运行时自动生成实现。 |
详细场景说明
DAO (Data Access Object)
DAO 模式的核心目的是解耦。业务层(Service)不需要知道数据是从 MySQL、Oracle 还是 MongoDB 取出来的,它只依赖 UserDAO 接口。
- 在 JPA/Hibernate 项目中:通常会有一个 UserDAO 接口,里面可能继承 JpaRepository,或者自己写 HQL。
- 在早期的 JDBC/MyBatis 项目中:你会看到 UserDAO 接口和 UserDAOImpl 实现类,实现类里写满了 SqlSession 调用或 JDBC 代码。
Mapper (映射器)
Mapper 是 MyBatis 的“杀手锏”。你只需要写一个接口(如 UserMapper.java)和一个 XML 文件(如 UserMapper.xml),MyBatis 会在运行时动态生成这个接口的实现类,并帮你执行 XML 里绑定的 SQL。
- 特点:接口里的方法名、参数、返回值,与 XML 里的 id、parameterType、resultType 一一对应。
- 本质:Mapper 其实就是 MyBatis 对你项目里“数据访问对象”的具体称呼。
为什么很多 MyBatis 项目里,包名用 dao 还是 mapper 都有?
这是一个历史习惯问题:
1. 包名用 dao:
开发者受传统 Java EE 教育影响,认为“这一层就是 DAO 层”,所以包名叫 dao。
里面的接口其实还是叫 UserMapper(因为要加 @Mapper 注解),或者叫 UserDAO 但本质是 Mapper。
现状:很多老项目或习惯传统的团队喜欢这么干。
2. 包名用 mapper:
开发者认为“既然技术栈是 MyBatis,那就明确告诉别人这是 Mapper”,见名知意。
里面的接口就叫 UserMapper。
现状:目前使用 MyBatis / MyBatis-Plus 的新项目,绝大多数推荐使用 mapper 作为包名,因为这是框架的原生术语,不会与 JPA 的 Repository 或传统 DAO 模式混淆。
选型建议(该用哪个?)
Java 项目技术栈如果是 MyBatis,坚持使用 mapper 包名和 XxxMapper 接口命名,是当前最主流、最清晰的企业级规范。
总结
DAO 是“做什么”(数据访问),Mapper 是“怎么做”(MyBatis 的 SQL 映射实现)。

浙公网安备 33010602011771号