MyBatis 多表查询三种最常见的写法

 更新时间:2025年04月22日 10:21:02   作者:扶风_w  
这篇文章主要介绍了MyBatis 多表查询三种最常见的写法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

前言:一张关联表,让你头秃了吗?

你是不是也写过这种需求:

  • 查询某个用户及其角色列表
  • 查询订单及明细
  • 查询项目及其下属的多个阶段和负责人

最后写了一堆复杂 SQL + resultMap,运行一看,要么数据重复、要么数据丢失,最惨还可能触发 N+1 查询……

其实问题不是 MyBatis 不行,而是你用的方法不对。

🔍 三种最常见的写法 

✅ 方式一:联表查询 + 扁平映射(推荐)

这是我最常用也最稳定的一种方式:写一条联表 SQL,把需要的字段都查出来,返回扁平结构,再在 Java 层进行组装。

示例 SQL:

SELECT u.id AS userId, u.name AS userName,
       r.id AS roleId, r.name AS roleName
FROM user u
LEFT JOIN user_role ur ON u.id = ur.user_id
LEFT JOIN role r ON ur.role_id = r.id

特点:

  • 一条 SQL 查全所有数据;
  • 性能高,逻辑直观;
  • 可与分页插件(如 PageHelper)完美配合。

我的建议:

Java 层用 Map<Long, UserDTO> 分组封装,适合在 Service 层统一做聚合逻辑。

⚙️ 方式二:嵌套结果(resultMap + collection)

适合结构较为清晰的“树状结构”,比如订单和订单项、项目和子模块。

示例 XML: 

<resultMap id="userMap" type="User">
  <id property="id" column="user_id"/>
  <result property="name" column="user_name"/>
  <collection property="roles" ofType="Role">
    <id property="id" column="role_id"/>
    <result property="name" column="role_name"/>
  </collection>
</resultMap>

特点:

  • 多表映射层级清晰;
  • 比较适合中小型数据量。

踩坑经验:

  • 写错列名字段,就会导致内层集合全是 null;
  • 出现重复数据时,要手动去重或用 Set;
  • 不适合配合分页,容易导致“分页的是主表,但集合是全量”。

🧩 方式三:嵌套查询(nested select)

适合逻辑解耦,按模块维护的场景。

示例 XML:

<collection property="roles" ofType="Role" select="selectRolesByUserId" column="id"/>

特点:

  • 每条主表数据触发一次副查询;
  • 易维护但 极易 N+1
  • 不适合大批量数据查询。

实战建议:

除非你能保证每次最多查询 10 条主记录,否则慎用。性能瓶颈很容易出现在这里!

📉 你可能踩过的坑

问题症状原因建议
查询结果为 null子集合没数据字段名或别名不匹配显式写 column 属性或使用 @Results 映射
一对多重复数据主表字段重复出现联表未分组 / Java 封装没处理手动分组聚合,避免直接用 List
分页异常只分页主表,子表数据混乱不支持嵌套分页联表 + 扁平查询是最佳方案
查询慢到爆炸N+1 查询每条主记录触发一次 select转成 join 联查或改为批量查

✅ 实战建议:如何选择这三种方式? 

类型性能可维护性适合场景
联表扁平查询⭐⭐⭐⭐⭐⭐⭐大批量、一对多、分页场景
嵌套结果 resultMap⭐⭐⭐⭐⭐⭐⭐结构清晰、数据量适中
子查询 nested⭐⭐⭐⭐⭐⭐⭐小数据量、逻辑独立场景

📦 我的最佳实践模板(真实项目用的)

  • DAO 层只查数据,不做结构组装
  • Service 层按业务模型拼装 DTO
  • 多表结果不要直接给前端,统一封装响应结构;
  • DTO + Builder 模式 + Map 分组,灵活好用;

📌 总结一句话:

多表查询选对方式,写代码少掉一半 bug。

不必纠结哪种方式最“完美”,关键是是否适合你当前场景
记住:能用联查查全的,就别搞子查询;分页场景尽量别用嵌套结构;小数据就图方便,结构优先。

到此这篇关于MyBatis 多表查询的文章就介绍到这了,更多相关MyBatis 多表查询内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解SpringIOC容器中bean的作用范围和生命周期

    详解SpringIOC容器中bean的作用范围和生命周期

    这篇文章主要介绍了SpringIOC容器中bean的作用范围和生命周期,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-02-02
  • java如何实现数位分离

    java如何实现数位分离

    这篇文章主要介绍了java如何实现数位分离,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • 详解Spring Security 简单配置

    详解Spring Security 简单配置

    本篇文章主要介绍了详解Spring Security 简单配置,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • SpringBoot监听Redis key失效事件的实现代码

    SpringBoot监听Redis key失效事件的实现代码

    这篇文章给大家介绍了SpringBoot实现监听Redis key失效事件的方法,文中通过代码示例给大家讲解的非常详细,具有一定的参考价值,需要的朋友可以参考下
    2024-02-02
  • Spring Boot插件spring tool suite安装及使用详解

    Spring Boot插件spring tool suite安装及使用详解

    这篇文章主要介绍了Spring Boot插件spring tool suite安装及使用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-08-08
  • 详解Java编程中对线程的中断处理

    详解Java编程中对线程的中断处理

    这篇文章主要介绍了Java编程中对线程的中断处理,特别讲解了中断的时机与中断状态的管理,需要的朋友可以参考下
    2015-11-11
  • 详解Java中String类型与默认字符编码

    详解Java中String类型与默认字符编码

    这篇文章主要介绍了Java中String类型与默认字符编码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-05-05
  • MyBatis-Plus将字段修改为空值的解决方案

    MyBatis-Plus将字段修改为空值的解决方案

    这篇文章主要介绍了MyBatis-Plus将字段修改为空值的解决方案,本文给大家分享三种常用的解决方案,感兴趣的朋友一起看看吧
    2023-12-12
  • Java实现蓝桥杯数独游戏的示例代码

    Java实现蓝桥杯数独游戏的示例代码

    这篇文章主要介绍了Java实现蓝桥杯数独游戏的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • Intellij IDEA实现SpringBoot项目多端口启动的两种方法

    Intellij IDEA实现SpringBoot项目多端口启动的两种方法

    有时候使用springboot项目时遇到这样一种情况,用一个项目需要复制很多遍进行测试,除了端口号不同以外,没有任何不同。遇到这种情况怎么办呢?这时候可以使用Intellij IDEA解决
    2018-06-06

最新评论