MyBatis 中 ResultMap 的作用详解:对比有 ResultMap 和没有 ResultMap 的写法差异
在 MyBatis 中,ResultMap 是一个核心概念,用于解决数据库字段与 Java 对象属性之间的映射问题。本文将通过一个实际案例,详细分析 ResultMap 的作用,并对比使用 ResultMap 和不使用 ResultMap 的两种不同写法。
一、ResultMap 的作用
ResultMap 的主要功能是显式定义数据库字段与 Java 对象属性的映射关系。它适用于以下场景:
- 字段名与属性名不一致:例如数据库字段为
order_addr_id,而 Java 对象属性为orderAddrId。 - 复杂映射:如关联查询(一对一、一对多)、类型转换等。
- 提高可读性:明确列出所有字段的映射关系,便于后续维护。
二、案例代码分析
以下是一个 MyBatis 映射文件(XML)的片段,其中定义了一个 ResultMap,但查询时却直接使用了 resultType:
<resultMap id="orderAddrMap" type="com.mall4j.cloud.order.model.OrderAddr">
<id column="order_addr_id" property="orderAddrId" />
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
<!-- 其他字段映射 -->
</resultMap>
<select id="list" resultType="com.mall4j.cloud.order.model.OrderAddr">
select <include refid="Vo_Column_List"/> from order_addr
</select>
虽然定义了 ResultMap,但查询语句中使用了 resultType 直接指向 Java 对象。这是否合理?下面分两种情况讨论。
三、没有 ResultMap 的写法(自动映射)
如果数据库字段名与 Java 属性名符合驼峰规则(例如 order_addr_id → orderAddrId),且 MyBatis 配置了自动驼峰转换,则可以省略 ResultMap。
1. 配置自动驼峰转换
在 mybatis-config.xml 中添加以下配置:
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
2. 查询语句
直接使用 resultType,依赖自动映射:
<select id="getByOrderAddrId" resultType="com.mall4j.cloud.order.model.OrderAddr">
select order_addr_id, create_time, user_id from order_addr
where order_addr_id = #{orderAddrId}
</select>
3. 优点
- 简洁:无需手动编写字段映射。
- 维护方便:字段增减时只需修改 SQL,无需调整
ResultMap。
4. 缺点
- 灵活性差:无法处理复杂映射(如关联对象、集合)。
- 依赖配置:必须启用
mapUnderscoreToCamelCase,否则字段无法正确映射。
四、使用 ResultMap 的写法(显式映射)
显式定义 ResultMap 可以完全控制映射逻辑,适合复杂场景。
1. 定义 ResultMap
<resultMap id="orderAddrMap" type="OrderAddr">
<id column="order_addr_id" property="orderAddrId"/>
<result column="create_time" property="createTime"/>
<result column="user_id" property="userId"/>
<!-- 其他字段映射 -->
</resultMap>
2. 查询语句
通过 resultMap 属性引用已定义的映射:
<select id="getByOrderAddrId" resultMap="orderAddrMap">
select order_addr_id, create_time, user_id from order_addr
where order_addr_id = #{orderAddrId}
</select>
3. 优点
- 灵活性高:支持复杂映射(如关联对象、集合)。
- 不依赖全局配置:即使不启用驼峰规则,也能正确映射。
- 可读性强:明确列出所有字段关系,便于团队协作。
4. 缺点
- 代码冗余:字段较多时需逐一定义。
- 维护成本:字段修改时需同步更新
ResultMap。
五、为什么案例中同时存在 ResultMap 和 resultType?
在用户提供的代码中,虽然定义了 ResultMap,但查询语句仍使用 resultType,可能有以下原因:
- 历史遗留问题:开发者可能未注意到已存在的
ResultMap。 - 依赖自动映射:已启用
mapUnderscoreToCamelCase,认为无需显式映射。 - 备用场景:
ResultMap可能用于其他复杂查询(如关联查询),而简单查询仍用resultType。
六、如何选择两种方式?
| 场景 | 使用 ResultMap | 使用 resultType(自动映射) |
|---|---|---|
| 字段名与属性名不一致 | ✅ 必须使用 | ❌ 无法处理 |
| 简单查询 | ⚠️ 可选 | ✅ 推荐 |
| 复杂查询(关联、集合) | ✅ 必须使用 | ❌ 无法处理 |
| 需要明确字段映射关系 | ✅ 推荐 | ⚠️ 不够直观 |
七、最终建议
- 启用自动驼峰映射:在简单场景中减少冗余代码。
- 复杂查询使用 ResultMap:确保灵活性。
- 保持一致性:团队统一约定使用风格,避免混用。