MyBatis魔法堂:结果集映射

作者:独泪了无痕日期:2026/6/14

一、ResultMap 的定义

在当今的软件开发领域,MyBatis 作为一款优秀的持久层框架,以其简洁的配置和强大的功能,深受广大开发者的喜爱。然而,在实际的项目开发中,我们常常会遇到数据模型与数据库表结构不一致的情况,这时就需要 MyBatis 的 resultMap 功能来帮助我们实现复杂的映射关系。想象一下,一个典型的业务场景:一个电商系统中的订单表,其字段包括订单ID、用户ID、商品ID、订单金额等。然而,在业务逻辑层,我们可能需要将订单信息与对应的用户信息和商品信息结合起来,以便于进行后续的业务处理。如果直接使用 MyBatis 的基本映射功能,我们只能获取到订单的基本信息,而无法获取到与之关联的用户和商品信息。这时,ResultMap 就显得尤为重要。

在 MyBatis 中,ResultMap 是核心概念之一,用于定义复杂映射关系的关键功能,它定义了 SQL 查询结果与 Java 对象之间的映射关系。它允许开发者将数据库表中的字段映射到实体类的属性上,同时也可以实现多表联合查询,将多个表的数据映射到一个实体类中。通过 ResultMap,我们可以轻松地实现数据模型与数据库表结构之间的映射,从而简化了数据访问层的开发。

二、基本配置

在开发过程中,我们经常会遇到数据库表与实体类(Entity)结构不一致的情况。例如,一个数据库表可能包含多个字段,而实体类只包含其中的一部分。在这种情况下,如果直接使用 MyBatis 的自动映射功能,可能会导致数据丢失或错误。映射关系是 ResultMap 的核心概念,它定义了数据库表字段与 Java 对象属性之间的对应关系。

标签映射类型简要说明
id主键映射将数据库中的主键字段映射到Java对象的属性上,用于唯一标识记录
result普通属性映射将数据库中的普通字段映射到Java对象的属性上
association关联映射将查询结果中的关联对象映射到Java对象的属性上
collection集合映射将查询结果中的集合对象映射到Java对象的属性上
select查询语句定义查询操作,指定查询结果映射规则
resultMap映射配置定义查询结果的映射规则,包括字段映射、关联映射和集合映射

2.1 resultMap:结果映射

ResultMap 是 MyBatis 框架中用于将数据库查询结果映射为 Java 对象的一种配置,它定义了如何将查询结果集中的列映射到 Java 对象的属性上。通过 resultMap,我们可以自定义字段与实体类属性的映射关系,从而实现灵活的数据转换。

1<resultMap id="BaseResultMap" type="com.lilith.entity.User">
2  <id column="id" property="id" />
3  <result column="user_name" property="userName" />
4  <result column="real_name" property="realName" />
5  <result column="sex" property="sex" />
6</resultMap>
7

一个标准的 resultMap 配置通常包含以下核心属性:

属性是否必须简要说明
id当前命名空间中的唯一标识符
type指定映射的目标 Java 类的全限定名或别名,指定 MyBatis 将查询结果封装成哪种类型的对象
extends用于继承其他resultMap,减少重复代码并提高代码的可维护性
autoMapping是否启用自动映射功能。如果开启(默认情况),自动将结果集中与 Java 对象属性同名(或符合驼峰命名规则)的列进行映射若设置为 false,则关闭自动映射,必须显式配置所有字段的映射关系

💡 根据 MyBatis 的 DTD 约束,resultMap 元素内的子元素必须按照特定顺序排列:constructor ➡️ id ➡️ result ➡️ association ➡️ collection ➡️ discriminator。

2.2 id:主键映射

id 标签是 resultMap 中的一个重要属性,用于指定实体类的主键字段,确保每次操作都能准确找到对应的实体对象。在查询数据时,MyBatis 会将查询结果中的主键值与实体类的主键字段进行映射。id 属性的配置对于正确实现结果映射至关重要,MyBatis 会用其值作为对象标识,提升缓存效率和对象比较准确性。

1<id property="id" column="user_id" javaType="int" jdbcType="INTEGER" />
2
属性是否必须简要说明
property指定实体类中对应的主键属性
column指定数据库表中的主键字段
javaType指定Java对象属性的数据类型
jdbcType指定SQL语句中占位符的JDBC类型
typeHandler实现Java类型与JDBC类型之间的自定义转换逻辑

2.3 result:普通字段映射

ResultMap 是一个 XML 元素,通常包含了一个或多个 Result 元素,每个 Result 元素用于指定实体类中的非主键字段与数据库表字段的映射关系。

1<result property="name" column="user_name" javaType="String" jdbcType="VARCHAR" />
2
属性是否必须简要说明
column对应数据库中的字段名。如果 SQL 中使用了别名,这里需填写别名
property对应 Java 实体类中的属性名
javaType一个 Java 类的全限定名,或一个类型别名
jdbcType指定数据库列类型,避免类型转换错误(如 NULL 值处理)
typeHandler指定类型处理器,用于处理Java类型与数据库类型之间的转换

2.4 association:一对一关联

一对一关联是指一个实体类对应数据库中的一张表,而另一个实体类与第一个实体类存在一对一的关系。在 MyBatis 中,可以使用 ResultMap 的子标签 association 来实现一对一映射,允许我们在查询一个对象时,同时获取其关联的对象。

1<association property="address" javaType="Address" column="address_id" select="selectAddressById" />
2
属性是否必须简要说明
property指定映射到实体类中的对象属性名称
column指定数据库表中对应的字段名或列别名,该字段的值将作为参数传递给嵌套查询
javaType指定该属性对应的 Java 类型
jdbcType
select指定另一个映射查询的 ID,MyBatis 会额外执行该 SQL 语句获取关联对象的结果
resultMap指定关联实体的映射配置
typeHandler
notNullColumn如果设置了该属性,只有当指定列的值为非 NULL 时才会执行关联查询,用于优化查询效率
columnPrefix当关联表的列名与主表的列名冲突时,可以为关联表的列名添加前缀以区分
resultSet
foreignColumn
autoMapping指定是否启用自动映射。默认为true,表示自动映射列到Java对象的属性忽略大小写
fetchType控制关联数据的加载方式,可选值为 lazy(延迟加载)或 eager(积极加载)

2.5 collection:一对多关联

一对多关联是指一个实体类对应数据库中的一张表,而另一个实体类与第一个实体类存在一对多的关系。在 MyBatis 中,可以使用 ResultMap 的子标签 collection 来实现一对多关联,允许我们在查询一个对象时,同时获取其关联的集合对象。

1<collection property="posts" javaType="ArrayList" column="id" ofType="Post" select="selectPostsForBlog"/>
2
属性是否必须简要说明
property指定映射到实体类中的对象属性名称
column指定数据库表中对应的字段名(或列别名),该字段的值将作为参数传递给嵌套查询
ofType指定集合中元素的Java类型
jdbcType指定该属性对应的 Java 类型
select指定另一个映射查询的 ID,MyBatis 会额外执行该 SQL 语句获取关联对象的结果
resultMap指定集合中元素的映射配置
typeHandler
notNullColumn如果设置了该属性,只有当指定列的值为非 NULL 时才会执行关联查询,用于优化查询效率。‌
columnPrefix当关联表的列名与主表的列名冲突时,可以为关联表的列名添加前缀以区分
resultSet
foreignColumn
autoMapping指定是否启用自动映射。默认为true,表示自动映射列到Java对象的属性忽略大小写
fetchType控制关联数据的加载方式,可选值为 lazy(延迟加载)或 eager(积极加载)

三、基本用法

3.1 简单映射

我们可以使用 resultMap 标签自定义结果集和实体类属性的映射规则,假设有一个 User 类,其属性与数据库中的字段不完全对应,可以这样定义 resultMap:

1<!-- 1️⃣、定义 resultMap -->
2<resultMap id="userResultMap" type="User">
3	<id property="id" column="user_id"/>
4	<result property="userName" column="user_name"/>
5	<result property="password" column="user_pwd"/>
6</resultMap>
7
8<!-- 2️⃣、在查询中引用 resultMap -->
9<select id="selectUserById" resultMap="userResultMap" parameterType="int">
10	SELECT user_id, user_name, user_pwd FROM users WHERE user_id = #{id}
11</select>
12

这样,无论字段名如何不同,MyBatis 都能根据 resultMap 将数据正确赋值到 User 对象上。

3.2 多表查询

有的时候需要查询多张表的数据才可以得到我们想要的结果,为此,可以直接写一个多表关联的SQL进行查询,也可以分步进行多次的查询来拿到我们需要的结果。Mybatis 就提供了对应的配置,可以让我们去更方便的进行相应的查询和对应的结果集处理。

关联映射(一对一)

假设每个用户都有一个详细地址信息,这里的地址信息相对于用户是一对一。在查询用户的同时查询用户的地址,可以在 resultMap 中配置如下:

1<resultMap id="addressMap" type="org.dllwh.mybatis.model.Address">
2  <id property="id" column="addr_id"/>
3  <result property="street" column="street"/>
4  <result property="city" column="city"/>
5  <result property="zipCode" column="zipCode"/>
6</resultMap>
7
8<resultMap id="userWithAddressMap" type="User">
9  <id property="id" column="id"/>
10  <result property="userName" column="userName"/>
11  <result property="nickName" column="nickName"/>
12  <!-- 一对一关联:使用 association 标签 -->
13  <association property="address" resultMap="addressMap" />
14</resultMap>
15
16<select id="selectUserWithAddress" resultMap="userWithAddressMap" parameterType="int">
17	select suu.*, a.* from sys_upms_user suu
18	left join address a on suu.id = a.user_id
19	where id = #{userId}
20</select>
21

如果有需要多表查询的需求,也可以选择用多次查询的方式来查询出想要的数据,Mybatis 也提供了对应的配置。例如获取查询用户时,还需查询出该用户所具有的地址信息。我们可以选择先查询User表查询用户信息,然后在去查询关联的地址信息。

1<!--
2	select属性:指定用哪个查询来查询当前属性的数据
3	column属性:设置当前结果集中哪列的数据作为select属性指定的查询方法需要参数
4-->
5<resultMap id="userWithAddressMap" type="User">
6  <id property="id" column="user_id"/>
7  <result property="userName" column="user_name"/>
8  <result property="password" column="user_pwd"/>
9  <!-- 关联映射,通过 user_id 关联地址 -->
10  <association property="address" column="id" select="selectAddressByUserId"/>
11</resultMap>
12
13<!-- 1️⃣、根据userId查询用户 -->
14<select id="selectUserWithAddress" resultMap="userWithAddressMap" parameterType="int">
15    SELECT user_id, user_name, user_pwd FROM users WHERE user_id = #{id}
16</select>
17
18<!-- 2️⃣、根据userId查询所具有的地址信息 -->
19<!-- 定义查询地址的 SQL -->
20<select id="selectAddressByUserId" resultType="Address" parameterType="int">
21    SELECT addr_id AS id, street, city, zip_code AS zipCode FROM address WHERE user_id = #{userId}
22</select>
23

集合映射(一对多)

假设每个用户可以有多个角色,两个实体之间是一对多的关系。例如在查询用户的同时,还需要该用户所具有的角色信息,可以在 resultMap 中配置如下:

1<!--定义User基本属性映射规则-->
2<resultMap id="userMap" type="org.dllwh.mybatis.model.SysUser">
3  <id property="id" column="id"/>
4  <result property="username" column="username" />
5	<result property="age" column="age" />
6	<result property="address" column="address" />
7  <collection property="roles" resultMap="userRoleMap"/>
8</resultMap>
9
10<resultMap id="userRoleMap" type="org.dllwh.mybatis.model.SysRole" >
11  <id property="id" column="roleId"/>
12  <result property="roleName" column="roleName"/>
13  <result property="roleCode" column="roleCode"/>
14</resultMap>
15
16<select id="getUserLst" resultMap="userMap">
17  SELECT suu.*, sur.*
18  from sys_upms_user suu
19  LEFT JOIN sys_upms_user_role suur on suur.userId = suu.id
20  LEFT JOIN sys_upms_role sur on suur.roleId = sur.id
21</select>
22

3.3 类型处理器

在 MyBatis 框架中,结果映射(Result Mapping)是核心功能之一,它负责将数据库查询结果映射到 Java 对象的属性上。类型处理器(Type Handler)是 MyBatis 提供的一种机制,用于处理 Java 类型与数据库类型之间的转换。类型处理器的工作原理是,当MyBatis在执行查询操作时,会根据SQL语句的结果集类型,调用相应的类型处理器进行数据转换。类型处理器内部定义了转换规则,将数据库中的数据类型转换为Java对象中的属性类型。

1public interface TypeHandler<T> {
2	// 将数据库类型转换为Java类型
3	T fromDatabaseType(Object databaseValue);
4	// 将Java类型转换为数据库类型
5	Object toDatabaseType(T javaObject);
6}
7

在 MyBatis 配置文件中,类型处理器与数据库类型映射是通过定义 typeHandler 属性来实现。例如,将 VARCHAR 类型的数据库字段映射到 Java 对象的 String 属性:

1<resultMap id="userResultMap" type="User">
2	<result column="name" property="name" typeHandler="com.example.MyCustomTypeHandler"/>
3</resultMap>
4

自定义类型处理器可以满足特定业务需求,以下是一个简单的自定义类型处理器示例:

1public class MyCustomTypeHandler implements TypeHandler<String> {
2  @Override
3  public String fromDatabaseType(Object databaseValue) {
4    // 将数据库类型转换为Java类型
5    return (String) databaseValue;
6  }
7
8  @Override
9  public Object toDatabaseType(String javaObject) {
10    // 将Java类型转换为数据库类型
11    return javaObject;
12  }
13}
14

四、总结

MyBatis 的 resultMap 提供了强大而灵活的机制,使得开发者能够精准地控制 SQL 查询结果与 Java 对象之间的映射关系。无论是简单的单表查询还是复杂的多表联合查询,通过合理设计 resultMap,都能大幅提高数据访问层代码的可读性、可维护性和性能。这种灵活性正是 MyBatis 被广泛使用的重要原因之一,也为开发者在实际项目中处理复杂数据模型提供了极大便利。


MyBatis魔法堂:结果集映射》 是转载文章,点击查看原文


相关推荐


不用 Mac 也可以 Windows下管理iOS描述文件的非Xcode完整指南
程序员不说人话2026/6/7

很多开发者第一次接触 iOS 描述文件(Provisioning Profile)时,看到的教程基本都围绕 Xcode 和钥匙串。 但实际开发里,有一类项目并不是在 Mac 上完成的、uni-app、Flutter、React Native、HBuilderX 云打包、Windows 开发环境,这时问题会变成.mobileprovision 文件到底怎么管理? 尤其项目一多之后,开发者会开始遇到 描述文件和证书不匹配、Bundle ID 混乱、测试设备漏加、文件过期后无法安装、不同电脑之间无法同


栗子前端技术周刊第 131 期 - pnpm 11.3、npm 11.16.0、Astro 6.4...
晓得迷路了2026/6/1

🌰栗子前端技术周刊第 131 期 (2026.05.25 - 2026.05.31):浏览前端一周最新消息,学习国内外优秀文章,让我们保持对前端的好奇心。 📰 技术资讯 pnpm 11.3:pnpm 11.3 版本更新,新增阶段性发布命令 pnpm stage、用于管控信任策略生效规则的 trustLockfile 配置,同时原生支持 pkg、repo、set-script 等命令,以及多项其他功能。 npm 11.16.0:npm 11.16.0 已正式发布,该版本初步支持可自主选


MySQL视图
Halvmån2026/5/10

我们上一篇博客也讲到了视图,但是我们今天要学的这个视图并不是上篇博客的视图。 在日常数据库开发中,我们经常遇到这样的需求:多个业务模块需要查询同一份数据,但每个模块关注的字段不同;或者某些敏感字段需要隐藏,不能让所有用户都看到。这时候,视图(View) 就成了一个非常优雅的解决方案。 很多人刚开始接触视图时,会觉得它像一个“虚拟表”或者“保存好的查询语句”。本文将从实际开发的角度,带你全面掌握 MySQL 视图的使用。 一、什么是视图? 视图是一个虚拟表,它不存储实际数据,而是存储一条 


Linux 线程同步与互斥(六) 线程安全与重入问题,死锁,线程done
codeacac2026/4/30

目录 一、线程安全与重入问题 概念 线程安全 重入 多线程重入函数 信号导致的重入 可重入与线程安全的联系 可重入与线程安全的区别 二、死锁 概念 造成死锁的4个必要条件 避免死锁的做法: 三、STL, 智能指针和线程安全 四、总结 一、线程安全与重入问题 概念 线程安全 线程安全就是当多个线程同时访问同一块资源(如全局变量、任务队列、打印终端)时,最终结果能符合预期,不会出现数据错乱、逻辑错误,这就是线程安全。 我们可以结合上一篇线程池的代码


把 Git 提交历史变成一条流动的河——Project River
仿生狮子2026/4/22

是什么 你有没有好奇过一个开源项目十年的贡献者活动长什么样?谁一直在写代码?谁是后来加入的?版本大升级时社区发生了什么变化? 我做了 Project River,一个 Git 历史可视化工具——输入一个 Git 仓库,能把每位贡献者的提交活动渲染成随时间流动的河流图(Streamgraph)。 项目地址:github.com/Lionad-Moro… 在线体验:lionad-morotar.github.io/project-riv… 直接看效果: 河流越宽,说明当天的提交越多。每条色带


React性能优化
whuhewei2026/4/13

React应用在复杂场景下容易出现渲染性能瓶颈,合理优化能显著提升用户体验。React性能优化手段的核心在于减少不必要的渲染、控制资源加载和合理使用缓存机制。 1. 使用 React.memo 避免子组件无意义重渲染 当父组件更新时,即使子组件props未变,也会默认重新渲染。React.memo可缓存组件输出,仅在props变化时重新更新。 示例Demo: import React, { useState } from "react"; const ExpensiveComponen


PHP $_GET 变量详解
froginwe112026/4/5

PHP $_GET 变量详解 引言 PHP $_GET 变量是 PHP 中用于处理 URL 查询字符串参数的一个内置数组。在 Web 开发中,$_GET 变量经常用于收集来自表单的数据或者从 URL 中提取信息。本文将详细介绍 PHP $_GET 变量的基本用法、操作方法和注意事项。 一、$_GET 变量简介 在 PHP 中,$_GET 是一个超级全局变量,用于存储通过 URL 传递的参数。这些参数以名值对的形式出现在 URL 中,如 http://www.example.com/?ke


go实战案例:如何基于 Consul 给微服务添加服务注册与发现?
五年小兵勇闯互联网2026/3/27

在单体应用向微服务架构演进的过程中,原本的巨石型应用会按照业务需求被拆分成多个微服务,每个微服务会提供特定的功能,并可能依赖于其他的微服务。每个微服务实例都可以动态部署,服务实例之间的调用通过轻量级的远程调用方式(HTTP、消息队列等)实现,它们之间通过预先定义好的接口进行访问。         由于服务实例是动态部署的,每个服务实例的地址和服务信息都可能动态变化,这就势必需要一个中心化的组件对各个服务实例的信息进行管理,该组件管理了各个部署好的服务实例元数据,包括服务名、IP地址、端口号、服务


VMware虚拟机CentOS磁盘扩容完整指南(解决growpart报错 & LVM扩容)
Microi风闲2026/3/19

文章目录 前言✨一、环境与背景二、第一阶段:VMware 层面扩容三、第二阶段:CentOS 系统内部扩容方法一:标准LVM扩容流程(推荐)方法二:解决 growpart 报错方案(备用) 四、总结与注意事项 前言✨ 在日常开发和运维中,我们经常遇到 VMware 虚拟机磁盘空间不足的问题。本文记录了如何为一台正在运行的 CentOS 7 虚拟机安全地扩容磁盘空间的全过程。本次操作不仅涵盖了标准的扩容步骤,还重点解决了实际操作中可能遇到的两个关键问题: growpart


OpenClaw实战-NAS配置从0到1详细教程及踩坑记录
可夫小子2026/3/11

💡 大家好,我是可夫小子,关注AI编程、AI自动化和自媒体。 背景 我去年在自己Macbook上就已经安装了Openclaw了,当时基本就是一行命令,比较顺利。经过这两个月,Openclaw版本经历了很多更新,当时的安装教程有些过时了。最近,我需要在一台群晖的Nas部署Openclaw,硬是花了两天时间才完成。我把整个详细的部署过程,一些踩坑经历用图文记录下来,就有这篇包含30多张截图的图文。 方案说明 在Nas安装Openclaw,主要有三种方案来实现 直接通过官方脚本,安装到Nas物

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2026 聚合阅读