开发者

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

目录
  • 一、嵌套查询(Nested Select)
    • 特点
    • 示例代码
    • 解释
  • 二、嵌套结果(Nested Results)
    • 特点
    • 示例代码
    • 解释
  • 三、递归查询(Recursive Query)
    • 特点
    • 示例代码
    • 解释
  • 四、使用 column 传递多个参数
    • 语法
    • 示例代码
    • 解释
  • 五、JavaType 和 ofType 的区www.devze.com
    • 示例
  • 总结:不同场景的适用性

    在 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)

    通过&nandroidbsp;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 -->
    <python;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="selectCategoriesByParentIdpython" 
            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 中的一对多映射需求。

    到此这篇关于MyB编程atis中<collection>标签的多种用法的文章就介绍到这了,更多相关MyBatis  collection标签内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜