MyBatis 中 ResultMap 的作用详解:对比有 ResultMap 和没有 ResultMap 的写法差异

1,092 阅读3分钟

MyBatis 中 ResultMap 的作用详解:对比有 ResultMap 和没有 ResultMap 的写法差异

在 MyBatis 中,ResultMap 是一个核心概念,用于解决数据库字段与 Java 对象属性之间的映射问题。本文将通过一个实际案例,详细分析 ResultMap 的作用,并对比使用 ResultMap 和不使用 ResultMap 的两种不同写法。

一、ResultMap 的作用

ResultMap 的主要功能是显式定义数据库字段与 Java 对象属性的映射关系。它适用于以下场景:

  1. 字段名与属性名不一致:例如数据库字段为 order_addr_id,而 Java 对象属性为 orderAddrId
  2. 复杂映射:如关联查询(一对一、一对多)、类型转换等。
  3. 提高可读性:明确列出所有字段的映射关系,便于后续维护。

二、案例代码分析

以下是一个 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_idorderAddrId),且 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,可能有以下原因:

  1. 历史遗留问题:开发者可能未注意到已存在的 ResultMap
  2. 依赖自动映射:已启用 mapUnderscoreToCamelCase,认为无需显式映射。
  3. 备用场景ResultMap 可能用于其他复杂查询(如关联查询),而简单查询仍用 resultType

六、如何选择两种方式?

场景使用 ResultMap使用 resultType(自动映射)
字段名与属性名不一致✅ 必须使用❌ 无法处理
简单查询⚠️ 可选✅ 推荐
复杂查询(关联、集合)✅ 必须使用❌ 无法处理
需要明确字段映射关系✅ 推荐⚠️ 不够直观

七、最终建议

  1. 启用自动驼峰映射:在简单场景中减少冗余代码。
  2. 复杂查询使用 ResultMap:确保灵活性。
  3. 保持一致性:团队统一约定使用风格,避免混用。