MyBatis中的collection两种使用方法

博客围绕表关系为1:n的查询需求,介绍了两种联查方式,涉及QuestionMapper.xml和QuestionOptionMapper.xml文件。同时提醒,当主子表要查询的字段名重复时,需要为字段起别名。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

表关系: 问题表 1==>n 问题选项表,
需求: 查询问题时候,联查出来问题选项

//问题 实体类
public class Question {
	private	String id; //ID
	private	String content; //问题
	private	String type; //问题类型 1:单选,2:多选,3:问答
	private	Integer sort; //排序
	private List<QuestionOption> options; //问题选项 *** 问题表里不需要有这个属性对应的字段
	//...
}
//问题选项 实体类
public class QuestionOption{
	private	String id; //ID
	private	String qid; //问题ID *** 问题选项表里需要有这个属性对应的字段
	private	String content; //选项
	private	Integer sort; //排序
	//...
}

方式一:

代码复用性高, 主表分页查询正确

QuestionMapper.xml

<mapper namespace="com.xxx.modules.xxx.mapper.QuestionMapper">

<resultMap id="BaseResultMap" type="com.xxx.modules.xxx.entity.Question" >
		<id column="id" 		 property="id"      jdbcType="VARCHAR" />
		<result column="content" property="content" jdbcType="VARCHAR" />
		<result column="type"    property="type"    jdbcType="VARCHAR" />
		<result column="sort"    property="sort"    jdbcType="INTEGER" />
		<collection property="options" javaType="java.util.ArrayList" ofType="com.xxx.modules.xxx.entity.QuestionOption"
					select="com.xxx.modules.xxx.mapper.QuestionOptionMapper.selectList" column="{qid=id,sort=sort}" />
		<!-- qid/sort是定义的变量名, id/sort是主表的字段id/sort,
		先查出主表的结果, 然后主表记录数是几 就执行几次 collection 的select,
		javaType和ofType 写不写都行,
		select的值: 对应xml的namespace + 对应xml中的代码片段的id,
		column作为select语句的参数传入,如果只传一个参数id可以简写: column="id" -->
	</resultMap>

	<!-- 查询列表 -->
	<select id="selectList" resultMap="BaseResultMap">
        SELECT
        	pq.id, pq.content, pq.type, pq.sort
        FROM
        	question AS pq
        <where>  
        </where>
    </select>

QuestionOptionMapper.xml

<mapper namespace="com.xxx.modules.xxx.mapper.QuestionOptionMapper">

 <!-- 查询列表 -->
 <select id="selectList" resultType="QuestionOption">
     SELECT
     	pqo.id, pqo.content, pqo.sort
     FROM
     	question_option AS pqo
     <where>
     	pqo.qid = #{qid} <!-- 变量名 qid 对应上文的 qid -->
     	<!-- 如果上文中 collection只传一个参数column="id",只要类型匹配,在这里随便写个变量名就可以取到值 #{xyz} -->
     </where>
 </select>

方式二:

只需要执行一次sql查询, 主表分页查询不正确

QuestionMapper.xml

<mapper namespace="com.xxx.modules.xxx.mapper.QuestionMapper">

<resultMap id="BaseResultMap" type="com.xxx.modules.xxx.entity.Question" >
		<id column="id" 		 property="id"      jdbcType="VARCHAR" />
		<result column="content" property="content" jdbcType="VARCHAR" />
		<result column="type"    property="type"    jdbcType="VARCHAR" />
		<result column="sort"    property="sort"    jdbcType="INTEGER" />
		<collection property="options" javaType="java.util.ArrayList" ofType="com.xxx.modules.data.entity.QuestionOption">
			<id column="oid" property="id" jdbcType="VARCHAR" />
			<result column="ocontent" property="content" jdbcType="VARCHAR" />
			<result column="osort" property="sort" jdbcType="INTEGER" />
		</collection>
		<!-- 列的别名 oid,ocontent,osort , 起别名是因为主子表都有这几个字段
			 这里要写 ofType, javaType还是可以不写 -->
	</resultMap>

	<!-- 查询列表 -->
	<select id="selectList" resultMap="BaseResultMap">
        SELECT
        	pq.id, pq.content, pq.type, pq.sort
        	,pqo.id AS oid ,pqo.content AS ocontent ,pqo.sort AS osort <!-- 联查子表字段,起别名 -->
        FROM
        	question AS pq
        	LEFT JOIN question_option pqo ON pq.id = pqo.qid <!-- 联查子表 -->
        <where>  
        </where>
    </select>
注意: 主子表要查询出来的字段名重复,要起别名

参考博客

### 使用 `collection` 标签进行集合映射 在 MyBatis 中,当涉及到一对多的关系时,可以使用 `collection` 标签来完成数据的映射。此标签主要用于处理一个对象对应多个其他对象的情形。 #### 集合映射的方式 存在两种方式实现 `collection` 的功能: - **嵌套结果映射** 这种方式通过单一 SQL 语句获取所有必要的信息并将其映射至相应的 Java 对象及其内部的列表属性中[^1]。例如,在查询部门信息的同时连带查出该部门下的所有员工记录,并将这些员工封装在一个 List 类型的成员变量里。 ```xml <resultMap id="DepartmentResult" type="com.example.Department"> <id property="deptId" column="DEPT_ID"/> <result property="name" column="NAME"/> <!-- 映射 Department 下的 Employees --> <collection property="employees" ofType="com.example.Employee"> <id property="empId" column="EMP_ID"/> <result property="name" column="EMP_NAME"/> </collection> </resultMap> <select id="getDeptWithEmployees" resultMap="DepartmentResult"> SELECT d.DEPT_ID, d.NAME AS DEPT_NAME, e.ID AS EMP_ID, e.NAME AS EMP_NAME FROM departments d LEFT JOIN employees e ON d.DEPT_ID = e.DEPARTMENT_ID; </select> ``` 上述代码片段展示了如何定义一个 Result Map 来描述从数据库读取的数据结构以及它们是如何被转换成应用程序内的复杂对象模型的一部分[^2]。 - **嵌套 select 查询** 另一种方法涉及两次独立的 SQL 调用——第一次用于检索父实体(如部门),第二次则针对每一个找到的父亲去查找其子项(即雇员们)。这种方法虽然可能不如前者高效,但它提供了更高的灵活性和更好的代码重用率[^5]。 ```xml <!-- 定义 Employee 结果集 --> <resultMap id="EmployeeResult" type="com.example.Employee"> <id property="empId" column="ID"/> <result property="name" column="NAME"/> </resultMap> <!-- 定义 Department 和它的 Employees 关系 --> <resultMap id="DepartmentWithNestedSelect" type="com.example.Department"> <id property="deptId" column="DEPT_ID"/> <result property="name" column="NAME"/> <collection property="employees" select="findEmployeesByDeptId" column="{DEPT_ID=deptId}" fetchType="lazy"/> </resultMap> <select id="findEmployeesByDeptId" resultType="com.example.Employee"> SELECT * FROM employees WHERE department_id=#{DEPT_ID} </select> ``` 这段 XML 片段说明了怎样利用 `<collection>` 元素配合另一个单独的选择器来进行延迟加载或即时加载操作[^4]。 #### 属性解释 对于 `collection` 标签而言,有几个重要的参数需要注意: - `property`: 表明当前集合所对应的实体类里的哪个字段。 - `ofType`: 指定集合内元素的具体类型,这有助于 MyBatis 正确地实例化目标类型的对象并将之加入到集合当中[^3]。
评论 38
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值