Mybatis 实现多表查询方式

  • 业务装配.对两个表编写单表查询语句,在业务(Service)把查询 的两个结果进行关联
  • 使用 Auto Mapping 特性,在实现两表联合查询时通过别名完成 映射.
  • 使用 MyBatis 的<resultMap>标签进行实现.
  • 多表查询时,类中包含另一个类的对象的分类

resultMap 标签

<resultMap>标签写在mapper.xml中,由程序员控制SQL查询结果与 实体类的映射关系.

  • 默认 MyBatis 使用 Auto Mapping 特性.
  • 使用 resultMap 标签时, select 标签不写 resultType 属性,而是使 用 resultMap 属性引用 resultMap 标签.
  • 使用 resultMap 实现单表映射关系

TIP

使用<resultMap>标签时,<select>标签不写 resultType 属性,而是使 用 resultMap 属性引用<resultMap>标签.

<demo>
<resultMap type="teacher" id="mymap">
<!-- 主键使用 id 标签配置映射关系 -->
<id column="id" property="id1" />
<!-- 其他列使用 result 标签配置映射关系 -->
<result column="name" property="name1"/>
</resultMap>

<select id="selAll" resultMap="mymap">
select * from teacher
</select>
</demo>

使用 resultMap 实现关联单个对象(N+1 方式)

  • N+1 查询方式,先查询出某个表的全部信息,根据这个表的信息 查询另一个表的信息

一对一

在 Student 实现类中包含了一个 Teacher 对象

  • 在 TeacherMapper 中提供一个查询
<select id="selById" resultType="teacher"
parameterType="int">
select * from teacher where id=#{0}
</select>
  • 在 StudentMapper 中
  • association 装配一个对象时使用
  • property: 对象在类中的属性名
  • select:通过哪个查询查询出这个对象的信息
  • column: 把当前表的哪个列的值做为参数传递给另 一个查询
  • 大前提使用 N+1 方式.时如果列名和属性名相同可以不配置,使用 Auto mapping 特性.但是 mybatis 默认只会给列专配一次
<demo>
 <!-- 
    方式一:嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集
             封装联表查询的数据(去除重复的数据)
        select * from class c, teacher t where c.teacher_id=t.t_id and c.c_id=1
    -->

	<!-- 使用resultMap映射实体类和字段之间的一一对应关系 -->
<resultMap type="student" id="stuMap">
	<id property="id" column="id"/>
	<result property="name" column="name"/>
	<result property="age" column="age"/>
	<result property="tid" column="tid"/>

<!-- 如果关联一个对象 -->
 <!-- 使用resultMap下面association 属性来完成1对1的映射-->
         <association property="teacher" javaType="com.qiu.entity.Teacher">
            <id property="id" column="t_id"/>
            <result property="name" column="t_name"/>
        </association>
		
</resultMap>

<select id="selAll" resultMap="stuMap">
select * from student
</select>
</demo>

简化一下

<demo>
 <!-- 
    方式二:嵌套查询:通过执行另外一个SQL映射语句来返回预期的复杂类型
        SELECT * FROM class WHERE c_id=1;
        SELECT * FROM teacher WHERE t_id=1   //1 是上一个查询得到的teacher_id的值
    -->
<resultMap type="student" id="stuMap">
<result column="tid" property="tid"/>
<!-- 如果关联一个对象 -->

	 
<association property="teacher"
select="com.b.mapper.TeacherMapper.selById"
column="tid"></association>
</resultMap>
<select id="selAll" resultMap="stuMap">
select * from student
</select>
</demo>

在mybatis中使用resultMap节点下的association标签来解决一对一的关联查询,association可用属性有:

  • property:对象属性的名称
  • javaType:对象属性的类型
  • column:所对应的外键字段名称
  • select:使用另一个查询封装的结果

一对多<resultMap>查询关联集合对象(N+1)

public class Teacher {
private int id;
private String name;
private List<Student> list;
  • StudentMapper.xml

    <select id="selByTid" parameterType="int"
    resultType="student">
    select * from student where tid=#{0}
    </select>
    

在 TeacherMapper.xml 中添加查询全部

  • <collection/> 当属性是集合类型时使用的标签

MyBatis中使用collection标签来解决一对多的关联查询,ofType属性指定集合中元素的对象类型。

<de>

<resultMap type="teacher" id="mymap">
		<id column="id" property="id"/>
		<result column="name" property="name"/>
	<collection property="list"
	select="com.b.mapper.StudentMapper.selByTid"
	column="id"></collection>
</resultMap>

<select id="selAll" resultMap="mymap">
select * from teacher
</select>
</de>

使用关联查询

  <!-- 
     嵌套结果: 使用嵌套结果映射来处理重复的联合结果的子集
    SELECT * FROM class c,student s WHERE c.C_id=s.class_id AND  c.c_id=1
     -->
    <select id="getClass3" parameterType="int" resultMap="ClassResultMap3">
        select * from class c, teacher t,student s where c.teacher_id=t.t_id 
and c.C_id=s.class_id and  c.c_id=#{id}
    </select>
    <resultMap type="com.qiu.entity.Classes" id="ClassResultMap3">
        <id property="id" column="c_id"/>
        <result property="name" column="c_name"/>
      
        <!-- ofType指定students集合中的对象类型 -->
        <collection property="students" ofType="com.qiu.entity.Student">
            <id property="id" column="s_id"/>
            <result property="name" column="s_name"/>
        </collection>
    </resultMap>

Auto Mapping 结合别名实现多表查询.

  • 只能使用多表联合查询方式
  • 在 SQL 是关键字符,两侧添加反单引号
<select id="selAll" resultType="student">
    select  t.id `teacher.id`  ,    t.name`teacher.name`
    , s.id id , s.name name  ,  age  ,  tid
from student s LEFT JOIN teacher t on t.id=s.tid
</select>