MyBatis中<collection>标签的多种用法

 更新时间:2025年04月02日 09:26:53   作者:愿你天黑有灯下雨有伞  
collection标签是处理一对多关系的关键工具,它能够将查询结果巧妙地映射到Java对象的集合属性中,本文主要介绍了MyBatis中<collection>标签的多种用法,感兴趣的可以了解一下

在 MyBatis 中,<collection> 标签是处理一对多(One-to-Many)关系的关键工具,它能够将查询结果巧妙地映射到 Java 对象的集合属性中。以下是 <collection> 的不同用法及其示例,结合知识库中的信息整理如下:

一、嵌套查询(Nested Select)

通过 select 属性引用另一个 SQL 查询,根据主表的某一列(如 id)作为参数,查询子表的集合数据。

特点

  • 每条主记录会触发一次子查询(可能导致 N+1 问题)。

  • 适合数据量较小或需要递归查询的场景。

示例代码

<!-- 主表的resultMap -->
<resultMap id="UserMap" type="User">
    <id property="id" column="id"/>
    <result property="username" column="username"/>
    <!-- 集合属性:permissions -->
    <collection 
        property="permissions" 
        ofType="Permission" 
        select="com.example.mapper.PermissionMapper.selectByUserId" 
        column="id"
    />
</resultMap>

<!-- 主表的查询SQL -->
<select id="selectUser" resultMap="UserMap">
    SELECT id, username FROM users WHERE id = #{id}
</select>

<!-- 子查询(PermissionMapper.xml) -->
<select id="selectByUserId" resultType="Permission">
    SELECT * FROM permissions WHERE user_id = #{id}
</select>

解释

  • property="permissions" :映射到 User 类的 permissions 集合属性。

  • ofType="Permission" :指定集合元素的类型。

  • select="..." :引用子查询的 Mapper 方法。

  • column="id" :将主表的 id 作为参数传递给子查询。

二、嵌套结果(Nested Results)

通过 column 和 ofType 直接映射 JOIN 查询的结果,避免多次查询数据库。

特点

  • 通过 JOIN 一次性获取所有数据,减少查询次数。

  • 需要处理重复数据(主表字段会被重复,需通过 columnPrefix 区分)。

示例代码

<!-- 主表的resultMap -->
<resultMap id="UserMap" type="User">
    <id property="id" column="user_id"/>
    <result property="username" column="username"/>
    <!-- 集合属性:orders -->
    <collection 
        property="orders" 
        ofType="Order" 
        columnPrefix="order_"
    >
        <id property="orderId" column="order_id"/>
        <result property="amount" column="amount"/>
    </collection>
</resultMap>

<!-- 主表的查询SQL(使用JOIN) -->
<select id="selectUserWithOrders" resultMap="UserMap">
    SELECT 
        u.id AS user_id, 
        u.username, 
        o.id AS order_id, 
        o.amount 
    FROM users u 
    LEFT JOIN orders o ON u.id = o.user_id 
    WHERE u.id = #{id}
</select>

解释

  • columnPrefix="order_" :将子表字段名前缀(如 order_id)与主表字段区分开。

  • <collection> 内部定义子表字段的映射规则。

  • 主表字段(如 user_id)和子表字段(如 order_id)通过别名区分。

三、递归查询(Recursive Query)

用于构建层级结构(如树形菜单、权限结构),通过 <collection> 自引用实现递归。

特点

  • 通过 select 属性引用自身或同级的查询方法,形成递归调用。

  • 适用于组织结构、分类树等场景。

示例代码

<!-- 处理树形结构的resultMap -->
<resultMap id="CategoryMap" type="Category">
    <id property="id" column="id"/>
    <result property="name" column="name"/>
    <result property="parentId" column="parent_id"/>
    <!-- 递归查询子节点 -->
    <collection 
        property="children" 
        ofType="Category" 
        select="selectCategoriesByParentId" 
        column="id"
    />
</resultMap>

<!-- 查询父节点的子节点 -->
<select id="selectCategoriesByParentId" resultMap="CategoryMap">
    SELECT * FROM categories WHERE parent_id = #{id}
</select>

解释

  • column="id" :将当前节点的 id 作为父节点 ID 传递给子查询。

  • <collection> 引用同一个 Mapper 中的 selectCategoriesByParentId 方法,形成递归。

  • 直到没有子节点时停止递归。

四、使用 column 传递多个参数

当子查询需要多个参数时,可以通过表达式指定多个列。

语法

column="{param1=column1, param2=column2}"

示例代码

<collection 
    property="items" 
    ofType="Item" 
    select="com.example.mapper.ItemMapper.selectItemsByUserAndDate" 
    column="{userId=id, date=createTime}"
/>

解释

  • 子查询 selectItemsByUserAndDate 需要两个参数:userId 和 date

  • column 表达式将主表的 id 映射为 userIdcreateTime 映射为 date

五、javaType 和 ofType 的区别

  • ofType :必须指定,用于定义集合中元素的类型(如 Permission)。

  • javaType :可选,指定集合的类型(如 ArrayList)。若不指定,MyBatis 默认使用 List

示例

<!-- 显式指定javaType -->
<collection 
    property="permissions" 
    javaType="ArrayList" 
    ofType="Permission" 
    select="..." 
    column="..."
/>

总结:不同场景的适用性

场景推荐用法优缺点
简单的一对多关系嵌套查询(select)简单易用,但可能引发 N+1 问题
需要 JOIN 一次性获取数据嵌套结果(columnPrefix)减少查询次数,但需处理重复字段和复杂 SQL
树形结构(如菜单、分类)递归查询(自引用)简洁且可自动构建层级,但需注意性能(尤其数据量大时)
需要传递多个参数column 表达式灵活传递多个参数,但需确保子查询参数匹配

通过合理选择 <collection> 的用法,可以高效地处理 MyBatis 中的一对多映射需求。

到此这篇关于MyBatis中<collection>标签的多种用法的文章就介绍到这了,更多相关MyBatis  collection标签内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring Boot与JWT和Shiro整合实践步骤(非常详细!)

    Spring Boot与JWT和Shiro整合实践步骤(非常详细!)

    这篇文章主要介绍了Spring Boot与JWT和Shiro整合的相关资料,将Shiro、Spring Boot和JWT集成在一起,可以大大提高应用程序的安全性,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-09-09
  • MybatisPlus使用idworker解决雪花算法重复

    MybatisPlus使用idworker解决雪花算法重复

    本文主要介绍了MybatisPlus使用idworker解决雪花算法重复,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-02-02
  • SpringBoot定时任务实现数据库数据同步全过程

    SpringBoot定时任务实现数据库数据同步全过程

    文章详细介绍了从简单到企业级数据库同步需求的技术方案,包括选型、实现步骤、优化方案、异常处理策略、生产环境配置建议等
    2025-12-12
  • dubbo扩展点AOP切面功能扩展示例详解

    dubbo扩展点AOP切面功能扩展示例详解

    这篇文章主要为大家介绍了dubbo扩展点AOP切面功能扩展示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • 如何基于java向mysql数据库中存取图片

    如何基于java向mysql数据库中存取图片

    这篇文章主要介绍了如何基于java向mysql数据库中存取图片,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • SpringBoot中打war包需要注意事项

    SpringBoot中打war包需要注意事项

    这篇文章主要介绍了SpringBoot中打war包需要注意事项,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • tk.mybatis实现uuid主键生成的示例代码

    tk.mybatis实现uuid主键生成的示例代码

    本文主要介绍了tk.mybatis实现uuid主键生成的示例代码,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-12-12
  • SpringBoot如何读取配置文件参数并全局使用

    SpringBoot如何读取配置文件参数并全局使用

    这篇文章主要介绍了SpringBoot如何读取配置文件参数并全局使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • elasticsearch索引创建create index集群matedata更新

    elasticsearch索引创建create index集群matedata更新

    这篇文章主要介绍了elasticsearch索引创建create index及集群matedata更新,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-04-04
  • 登录EasyConnect后无法通过jdbc访问服务器数据库问题的解决方法

    登录EasyConnect后无法通过jdbc访问服务器数据库问题的解决方法

    描述一下近期使用EasyConnect遇到的问题,下面这篇文章主要给大家介绍了关于登录EasyConnect后无法通过jdbc访问服务器数据库问题的解决方法,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-02-02

最新评论