此种方式需要查询数据库两次,发出两次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>