一、一对一
一般一对一使用 <association> 标签
<association>标签的常用属性如下:
- property:返回类型参数,一般为实体类的变量名一样即可
- select:另一个映射查询的 id, MyBatis 会额外执行这个查询获取嵌套对象的结果
- column:列名(或者别名),将主查询中列的结果作为嵌套查询的参数,配置方式如下 column={propl=coll , prop2=col2}, propl 和 prop2 将作为嵌套查询的参数。
- fetchType:数据加载方式,可选值为 lazy 和 eager,分别为延迟加载和积极加载
创建2张实体表
// 员工表
public class Employee {
private Integer id;
private String lastName;
private String gender;
private String email;
private Department dept; //一对一,一个员工对应一个公司
}
// 公司表
public class Department {
private Integer id;
private String departmentName;
}
- 使用查询2张表关联对象映射方式
<resultMap type="com.mybatis.domain.Employee" id="myEmp">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
<result column="gender" property="gender"/>
<result column="email" property="email"/>
<!-- 关联对象 -->
<association property="dept" javaType="com.mybatis.domain.Department">
<!-- 关联条件Employee的dept_id对应着Department的id -->
<id column="dept_id" property="id"/>
<result column="department_name" property="departmentName"/>
</association>
</resultMap>
<!-- resultMap指定使用上面定义的结果集,查询使用关联查询,查询列要和上面的column对应 -->
<select id="getEmpAndDeptById" resultMap="myEmp">
select e.id,e.last_name,e.gender,e.email,e.dept_id,d.id,d.department_name
from tbl_employee e,tbl_department d
where e.dept_id = d.id and e.id=#{id}
</select>
- 使用嵌套查询方式,则子查询依赖上一级查询返回的结果
// 对应DepartmentMapper
<select id="getDeptById" resultType="com.mybatis.domain.Department">
select * from tbl_department
where id = #{id}
</select>
// 对应EmployeeMapper
<mapper namespace="com.mybatis.mapper.EmployeeMapperPlus">
<resultMap type="com.mybatis.domain.Employee" id="myEmpByStep">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
<result column="gender" property="gender"/>
<result column="email" property="email"/>
<!-- 使用select属性指定第二步调用的方法,并通过column指定传递的参数值,这个值是第一步的查询的数据 -->
<association property="dept"
select="com.mybatis.mapper.DepartmentMapper.getDeptById"
column="dept_id">
</association>
</resultMap>
<!-- 第一步值只查询tbl_employee表 -->
<select id="getEmpAndDeptByStep" resultMap="myEmpByStep">
select id,last_name,gender,email,dept_id
from tbl_employee
where id = #{id}
</select>
</mapper>
二、一对多
使用<collection >标签,有两种使用方式
- 代码复用性高, 主表分页查询正确(嵌套查询) 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
</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="o_id" property="id" jdbcType="VARCHAR" />
<result column="o_content" property="content" jdbcType="VARCHAR" />
<result column="o_sort" property="sort" jdbcType="INTEGER" />
</collection>
<!-- 列的别名 o_id,o_content,o_sort , 起别名是因为主子表都有这几个字段
这里要写 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>