当前位置: 首页 > news >正文

resultMap和resultType

好的,这是一个非常核心的MyBatis面试题和日常开发中的关键知识点。resultMap 和 resultType 都用于指定SQL查询结果的返回类型,但它们的用法和能力有本质区别。

下面我用一个清晰的对比和示例来帮你彻底理解。

一、核心区别总结

 
 
特性 resultType resultMap
映射方式 自动映射 (基于约定) 手动映射 (基于显式配置)
控制力 弱,MyBatis自动完成,你无法干预过程 强,你完全掌控映射的每一个细节
配置 简单,只需指定一个Java类的全限定名 复杂,需要额外编写 <resultMap> 标签
列名 vs 属性名 必须一致(或开启驼峰命名规则) 可以任意不同,你手动指定对应关系
复杂关系 无法处理关联对象(如一对一、一对多) 可以处理复杂的关联查询和嵌套结果
适用场景 简单查询、字段名与属性名完全对应 几乎所有正式项目场景,尤其是不一致和有关联时

二、工作原理对比

1. resultType (自动映射)

当你使用 resultType 时,你是在对MyBatis说:

“嗨,MyBatis,这是我想要的结果类型(例如 com.example.User)。你自己想办法把查询结果的列名和我这个类里的属性名对应上吧。”

  • 如何对应? MyBatis会查看查询结果返回的列名(user_nameuser_age),然后尝试在Java类中寻找同名的属性(user_nameuser_age)。如果开启了 mapUnderscoreToCamelCase 配置,它会尝试将下划线命名转换为驼峰命名(user_name -> userName)。

  • 风险:如果数据库列名和Java属性名不匹配,对应的属性就会为 null,而且不会有任何错误提示,这是一个潜在的Bug源。

示例:

xml
<select id="findUser" resultType="com.example.User">SELECT user_id, user_name, user_age FROM t_user WHERE user_id = #{id}
</select>
java
public class User {private Integer userId;   // 能映射上 (开启驼峰规则后 user_id -> userId)private String userName;  // 能映射上 (开启驼峰规则后 user_name -> userName)private Integer age;      // 映射失败!数据库返回的是 user_age,但属性是 age。最终 age=null。
}

2. resultMap (手动映射)

当你使用 resultMap 时,你是在对MyBatis说:

“嗨,MyBatis,我亲自告诉你数据库的列和Java类的属性是怎么对应的。你就严格按照我给的这份‘说明书’(即 <resultMap>)来组装对象。”

你完全掌控了映射过程,无论名字是否一样。

示例:

xml
<!-- 首先,定义一份“说明书” -->
<resultMap id="UserResultMap" type="com.example.User"><id property="userId" column="user_id" /> <!-- 指定主键映射 --><result property="userName" column="user_name" /> <!-- 指定普通字段映射 --><result property="age" column="user_age" /> <!-- 即使名字完全不同,也能正确映射 -->
</resultMap><!-- 然后,在SQL中引用这份说明书 -->
<select id="findUser" resultMap="UserResultMap">SELECT user_id, user_name, user_age FROM t_user WHERE user_id = #{id}
</select>
java
public class User {private Integer userId;private String userName;private Integer age; // 现在这个属性也能正确接收到 user_age 列的值了!
}

三、核心能力差异详解

1. 处理关联关系(这是 resultMap 的杀手锏)

resultType 完全无法处理这种情况,而 resultMap 可以轻松搞定。

场景:查询用户信息的同时,获取他所在的部门信息(一个用户属于一个部门)。

java
// Java实体类
public class User {private Integer id;private String name;private Department department; // 一个用户关联一个部门对象
}
public class Department {private Integer id;private String deptName;
}

使用 resultMap 的解决方案:

xml
<!-- 1. 先定义Department的映射 -->
<resultMap id="DepartmentResultMap" type="Department"><id property="id" column="dept_id"/><result property="deptName" column="dept_name"/>
</resultMap><!-- 2. 再定义User的映射,并关联Department -->
<resultMap id="UserWithDeptResultMap" type="User"><id property="id" column="user_id"/><result property="name" column="user_name"/><!-- 使用 association 处理“一对一”关联 --><association property="department" resultMap="DepartmentResultMap"/>
</resultMap><!-- 3. 使用关联查询SQL -->
<select id="findUserWithDepartment" resultMap="UserWithDeptResultMap">SELECTu.id as user_id,u.name as user_name,d.id as dept_id,    <!-- 部门字段 -->d.name as dept_name  <!-- 部门字段 -->FROM user uLEFT JOIN department d ON u.dept_id = d.idWHERE u.id = #{id}
</select>

这样一次查询,返回的 User 对象里面的 department 属性就已经被完整地填充好了。

2. 处理集合关系(一对多)

场景:查询一个部门的同时,获取该部门下的所有员工。

java
public class Department {private Integer id;private String deptName;private List<User> employees; // 一个部门有多个员工
}
xml
<resultMap id="DepartmentWithUsersResultMap" type="Department"><id property="id" column="dept_id"/><result property="deptName" column="dept_name"/><!-- 使用 collection 处理“一对多”关联 --><collection property="employees" ofType="User" resultMap="UserResultMap"/>
</resultMap>

四、如何选择?最佳实践

  1. 永远首选 resultMap: 在正式的、复杂的项目开发中,几乎总是使用 resultMap。它提供了明确的映射关系,避免了因命名变化导致的隐性BUG,代码意图更清晰,可维护性更强。

  2. 何时用 resultType: 仅用于非常简单的、快速的测试或原型开发,或者当你查询的只是一个简单的字段(如 SELECT COUNT(*))时,你可以用 resultType="java.lang.Integer"

  3. 开启驼峰命名: 即使你决定在某些简单场景使用 resultType,也应在 mybatis-config.xml 中设置 <setting name="mapUnderscoreToCamelCase" value="true"/>,让自动映射更智能。

结论:
resultMap 是功能强大的手动模式,而 resultType 是简单但受限的自动模式。 把 resultMap 想象成专业相机的手动挡,一切参数由你控制;而 resultType 是自动挡,简单但无法应对复杂场景。对于严肃的开发,请使用手动挡(resultMap)。

http://www.hskmm.com/?act=detail&tid=10431

相关文章:

  • 直播软件怎么开发,自适应两栏布局方式 - 云豹科技
  • resultMap和自定义映射结果形式(ResultMapManage)以及ResultMap Vs ResultType
  • 嵌入式设备不能正常上网问题
  • 2、论文固定模板(背景过度结尾)
  • go: 图片文件上传
  • go: 生成缩略图
  • git: 报错: fatal: 协议错误:错误的行长度字符串:This 或 fatal: protocol error: bad line length character: This
  • jquery: Justified gallery
  • 安装crmeb
  • gin: 用zap记录访问日志
  • gin: 打包模板文件、静态文件到二进制文件中
  • gin: 判断是否ajax请求
  • gin: 静态文件
  • 详细介绍:【论文精读】基于YOLOv3算法的高速公路火灾检测
  • MacOS 下fuzz学习踩坑点
  • An Empirical Study on Commit Message Generation using LLMs via In-Context Learning 论文笔记
  • 实用指南:人工智能学习:Transformer结构中的编码器层(Encoder Layer)
  • vcpkg 安装依赖
  • Java03课前问题列表
  • JavaScript错误处理完全指南:从基础到自定义错误实战
  • 1、论文准备
  • PION 游击
  • Web3 开发者修炼全图谱:从 Web2 走向 Web3 的实用的系统性学习指南
  • 实用指南:医院高值耗材智能化管理路径分析(下)
  • Flutter应用自动更新系统:生产环境的挑战与解决方案
  • .NET Core中使用SignalR
  • 实用指南:修复Conda连接异常:CondaHTTPError HTTP 000 CONNECTION FAILED故障排除指南
  • 高级数据结构手册
  • Tarjan 学习笔记
  • 使用JavaScript和CSS创建动态高亮导航栏