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
映射为userId
,createTime
映射为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)!
精彩评论