MyBatis的resultType和resultMap的区别
一、引言
在使用 MyBatis 进行数据库连接操作时,对于 SQL 语句返回结果的处理通常有两种方式:resultType和resultMap。这两种方式各有其适用场景和特点,理解它们的区别对于编写高效、清晰的 MyBatis 映射文件至关重要。本文将详细介绍这两种结果映射方式,并结合实际代码示例,帮助你根据不同的查询需求做出合适的选择。
二、resultType:简单直接的映射
2.1 基本概念与使用
resultType是 MyBatis 中最直接的结果映射方式。当使用 resultType 时,SQL 查询出的字段名必须与 POJO(Plain Old Java Object)中的属性名完全一致(或遵循驼峰命名转换规则),MyBatis 会自动将查询结果映射到指定类型的对象中。
resultType 的值通常是 POJO 在项目中的全限定类名或别名。
2.2 适用场景与优缺点
适用场景:
- 单表查询:查询的字段与 POJO 属性一一对应时,使用 resultType 最为合适。
- 简单查询:查询结果不需要复杂的关联映射。
优点:
- 配置简单,无需额外定义 resultMap。
- 代码简洁,易于理解。
缺点:
- 字段名必须严格匹配,灵活性较差。
- 无法处理复杂的关联查询(如一对一、一对多)。
2.3 多表查询的变通处理
虽然 resultType 主要用于单表映射,但在多表连接查询时,也可以通过创建“组合 POJO”来变通使用:
- 一对一查询:新建一个 POJO,包含两个表中需要查询的所有字段。通常做法是创建一个继承自主表 POJO 的类,并添加从表所需字段。
- 一对多查询:若使用内连接,查询结果可能出现重复记录。此时需要在业务层(如 Service)中通过双重 for 循环进行去重和组装。
这种方式虽然可行,但会使得 POJO 设计变得复杂,且业务层逻辑繁重,因此对于复杂的关联查询,更推荐使用 resultMap。
三、resultMap:强大灵活的映射
3.1 基本概念与定义
resultMap是 MyBatis 中功能更强大的结果映射方式。它允许你在 mapper.xml 文件中显式地定义数据库字段与 Java 对象属性之间的映射关系,从而解除了字段名必须与属性名严格匹配的限制,并能够处理复杂的对象关联。
一个基本的 resultMap 定义如下:
<!-- 订单查询关联用户的 resultMap --> <!-- 将整个查询的结果映射到 cn.itcast.mybatis.po.Orders 中 --> <resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersUserResultMap"> <!-- 配置映射的订单信息 --> <!-- id:指定查询列中的唯一标识,订单信息的唯一标识,如果有多个列组成唯一标识,配置多个id column:订单信息的唯一标识列 property:订单信息的唯一标识列所映射到 Orders 中哪个属性 --> <id column="id" property="id"/> <result column="user_id" property="userId"/> <result column="number" property="number"/> <result column="createtime" property="createtime"/> <result column="note" property="note"/> </resultMap>3.2 处理一对一关联(association)
当查询涉及两个具有一对一关系的表时(如订单和用户),可以在主表的 POJO 中添加另一个表的 POJO 作为属性,然后在 resultMap 中使用<association>元素进行映射。
示例:查询订单及其关联的用户信息
<resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersUserResultMap"> <!-- 订单基本信息映射 --> <id column="id" property="id"/> <result column="user_id" property="userId"/> <result column="number" property="number"/> <result column="createtime" property="createtime"/> <result column="note" property="note"/> <!-- 配置映射的关联的用户信息 --> <!-- association:用于映射关联查询单个对象的信息 property:要将关联查询的用户信息映射到 Orders 中哪个属性 --> <association property="user" javaType="cn.itcast.mybatis.po.User"> <!-- id:关联查询用户的唯一标识 column:指定唯一标识用户信息的列 property:映射到 user 的哪个属性 --> <id column="user_id" property="id"/> <result column="username" property="username"/> <result column="sex" property="sex"/> <result column="address" property="address"/> </association> </resultMap>这样,查询结果会自动将用户信息封装到 Orders 对象的 user 属性中。
3.3 处理一对多关联(collection)
一对多关系(如一个订单对应多条订单明细)是实际开发中常见的场景。如果不对 SQL 语句进行特殊处理,由于一个订单对应多条明细,查询结果中订单信息会出现重复。
resultMap 的解决方案是:在主表 POJO 中添加一个 List 属性来存放从表的数据,并在 mapper.xml 中使用<collection>元素进行映射。
示例:查询订单及其所有订单明细
<!-- 订单及订单明细的 resultMap --> <!-- 使用 extends 继承,不用在中配置订单信息和用户信息的映射 --> <resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersAndOrderDetailResultMap" extends="OrdersUserResultMap"> <!-- 订单信息 --> <!-- 用户信息 --> <!-- 使用 extends 继承,不用在中配置订单信息和用户信息的映射 --> <!-- 订单明细信息 一个订单关联查询出了多条明细,要使用 collection 进行映射 collection:对关联查询到多条记录映射到集合对象中 property:将关联查询到多条记录映射到 cn.itcast.mybatis.po.Orders 哪个属性 ofType:指定映射到 list 集合属性中 pojo 的类型 --> <collection property="orderdetails" ofType="cn.itcast.mybatis.po.Orderdetail"> <!-- id:订单明细唯一标识 property:要将订单明细的唯一标识映射到 cn.itcast.mybatis.po.Orderdetail 的哪个属性 --> <id column="orderdetail_id" property="id"/> <result column="items_id" property="itemsId"/> <result column="items_num" property="itemsNum"/> <result column="orders_id" property="ordersId"/> </collection> </resultMap>通过这种方式,虽然一条订单信息对应多条订单明细,但由于将多条明细存储到了 List 集合中,查询后将不再出现重复的订单数据,达到了去重的效果。
四、resultType 与 resultMap 对比总结
| 对比项 | resultType | resultMap |
|---|---|---|
| 映射方式 | 自动映射,字段名与属性名需一致 | 手动映射,可自定义字段与属性的对应关系 |
| 配置复杂度 | 简单,无需额外配置 | 复杂,需显式定义映射关系 |
| 灵活性 | 较低,受限于命名规范 | 高,可处理复杂映射和关联 |
| 适用场景 | 单表简单查询 | 多表关联查询、复杂映射、字段名不一致 |
| 性能 | 较高(自动映射) | 稍低(需解析映射配置) |
| 代码可读性 | 高(直观简单) | 取决于映射定义的清晰度 |
五、实践建议与选择策略
- 简单查询优先使用 resultType:对于单表查询或字段名与属性名完全匹配的场景,使用 resultType 可以让代码更简洁。
- 复杂关联必须使用 resultMap:涉及一对一、一对多关联查询时,resultMap 是唯一的选择。
- 考虑使用继承简化配置:如示例所示,通过 extends 属性继承已有的 resultMap,可以避免重复配置,提高可维护性。
- 注意性能影响:虽然 resultMap 功能强大,但复杂的嵌套映射可能会影响性能。在设计时应权衡功能需求与性能要求。
- 保持映射清晰:为每个 resultMap 添加清晰的注释,说明其用途和映射关系,便于团队协作和后期维护。
六、结语
resultType 和 resultMap 是 MyBatis 中处理查询结果的两种核心方式,它们各有优劣,适用于不同的场景。理解它们的原理和适用条件,能够帮助你在实际开发中做出更合理的技术选型,编写出既高效又易于维护的数据访问层代码。建议在项目初期就根据业务复杂度规划好映射策略,避免后期因映射混乱导致的维护困难。
