此种方式需要查询数据库两次,发出两次sql语句,一次是查询tbl_phone表,一次是查询tbl_person表,但是数据库返回的信息没有冗余,mapper.xml配置和测试代码如下。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.wxy.dao.PersonDao">
<resultMap type="Phone" id="selectPhomap">
<id property="id" column="id"/>
<result property="phoneNum" column="phoneNum"/>
<collection property="persons" ofType="Person" select="selectPer" column="id">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="password" column="password"/>
<result property="gender" column="gender"/>
<result property="age" column="age"/>
<result property="phoneID" column="phoneID"/>
</collection>
</resultMap>
<select id="select" parameterType="int" resultMap="selectPhomap">
select * from tbl_phone where id=#{id}
</select>
<select id="selectPer" parameterType="int" resultType="Person">
select * from tbl_person where phoneID=#{phoneID}
</select>
</mapper>
用直白的话来描述此种方式,在调用mapper接口中的select方法,先走语句“select * from tbl_phone where id=#{id}”,从数据库中拿到返回数据之后,开始做返回值映射,此时的返回值映射对象是一个resultMap(id:selectPhomap),该resultMap实际上是一个Phone实例,因此在开始做映射的时候,id和phoenNum因为属性名和数据库返回值一致完成映射,但是到了persons属性的时候,发现他是一个collection集合对象,里面存放的是Person实例,那怎么获取里面的数据?看collection标签的属性,他需要关联一个查询操作select="selectPer"获取其数据,即通过select * from tbl_person where phoneID=#{phoneID}获取collection中的数据,select="selectPer"操作需要传入数据,传入的数据column="id"即是第一次查询中返回的phone id,这个在这里显得不明显,在第二种方式中会更加的明显,这里也是mybatis关联查询的核心点,最后一步,就是将第二次查询出来的数据映射到collection中。详细过程,通过打印日志也可窥见一斑 聚集元素用来处理“一对多”的关系。需要指定映射的Java实体类的属性,属性的javaType(一般为ArrayList);列表中对象的类型ofType(Java实体类);对应的数据库表的列名称;
不同情况需要告诉MyBatis 如何加载一个聚集。MyBatis 可以用两种方式加载:
1. select: 执行一个其它映射的SQL 语句返回一个Java实体类型。较灵活但会将执行多次嵌套的SQL语句。
2. resultMap: 使用一个嵌套的结果映射来处理通过join查询结果集,映射成Java实体类型。
两种加载方式格式如下:
1.集合的嵌套查询(select)
<collection property="Java属性名" ofType="另一Java类名" javaType="ArrayList" column="关联主键ID(用于嵌套查询SQL语句传入参数,多个用逗号分开)" select="另一个select映射SQL的ID"/>
<select parameterType="int" resultType="另一Java类名" id="另一个select映射SQL的ID">
SQL语句
<select>
注意:column属性的值必须与相应的SQL查询语句中的列名相同。MyBatis会将第一条SQL语句查询出来的该列的值用于所嵌套的SQL映射语句的入参。因第一条SQL语句查询出来的每个该列的值都将用于执行另一个SQL语句,所以嵌套的SQL语句将被多次执行。
2.集合的嵌套结果(resultMap)
<collection property="Java属性名" ofType="另一Java类名" javaType="ArrayList" resultMap="另一个resultMap的ID"/>
<resultMap="另一个resultMap的ID" type="另一Java类名">
<id property="id" column="关联主键ID"/>
........
</resultMap>
注意:column属性的值必须与相应的SQL查询语句的列名一样。
<resultMap id="roleDetailMap" type="cn.piesat.entity.DataRole" >
<id column="id" property="id" jdbcType="INTEGER" />
<result column="name" property="name" jdbcType="VARCHAR" />
<result column="remark" property="remark" jdbcType="VARCHAR" />
<collection property="privilege" column="id" ofType="cn.piesat.entity.Privilege" select="selectPrivileges" >
<id column="id" property="id" jdbcType="INTEGER" />
<result column="variable" property="variable" jdbcType="VARCHAR" />
<result column="name" property="name" jdbcType="VARCHAR" />
<result column="remark" property="remark" jdbcType="VARCHAR" />
<result column="device_id" property="deviceId" jdbcType="VARCHAR" />
</collection>
</resultMap>
<select id="selectPrivileges" parameterType="String" resultType="cn.piesat.entity.Privilege">
select id,name,variable,remark ,device_id deviceId from privilege where id in (select priv_id from role_privilege where role_id = #{id})
</select>
<select id="queryRoleDetail" resultMap="roleDetailMap" parameterType="java.lang.String" >
select
<include refid="Base_Column_List" />
from data_role
where id = #{id}
</select>
一对一关联查询
<!-- namespace命名空间,唯一标识。一般指定为自定义的接口文件,下面相当于这个接口的实现类 -->
<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>