JavaEE--Mybatis学习笔记(五)--关联关系查询

1.关联查询

  当查询内容涉及到具有关联关系的多个表时,就需要使用关联查询。根据表与表间的关联关系的不同,关联查询分为四种:

  (1)一对一关联查询

  (2)一对多关联查询

  (3)多对一关联查询

  (4)自关联

  (5)多对多关联查询

  由于日常工作中最常见的关联关系是一对多、多对一与多对多,所以这里就不专门只讲解一对一关联查询了,其解决方案与多对一解决方案是相同的。

  • 一对多关联查询

    这里的一对多关联查询是指,在查询一方对象的时候,同时将其所关联的多方对象也都查询出来

    下面是国家Country 与 部长Minister间的一对多关系进行演示.

    • 建表

  country表

  minister表

  • 实体

  • 一对多通过多表连接查询实现
<mapper namespace="com.ryanxu.dao.ICountryDao">
    <resultMap type="Country" id="countryMapper">
        <id column="cid" property="cid" />
        <result column="cname" property="cname" />
        <collection property="ministers" ofType="Minister">
            <id column="mid" property="mid" />
            <result column="mname" property="mname" />
        </collection>
    </resultMap>
    
    <select id="selectCountryById" resultMap="countryMapper">
        select cid,cname,mid,mname
        from country join minister on country.cid = minister.countryId
        where cid = #{id}
    </select>
</mapper>
注意 result里面 column和property之间要有空格 不然会报错
Cause: org.xml.sax.SAXParseException: Element type "result" must be followed by either attribute specifications, ">" or "/>".

因为是多表查询 返回的有minister的成员变量 若resultType使用的是Country 则没有mid和mname的get/set方法 所以使用resultMapper 将返回的包装成Country类 collection就是Set里面就是minister
  •  测试

    • 一对多通过多表单独查询实现
    <select id="selectMinisterByCountry" resultType="Minister">
        select mid,mname from minister where countryId = #{ryanxu}
    </select>
    
    <resultMap type="Country" id="countryMapper">
        <id column="cid" property="cid"/>
        <result column="cname" property="cname"/>
        <collection property="ministers"
                    ofType="Minister"
                    select="selectMinisterByCountry"
                    column="cid"/>
    </resultMap>
    <select id="selectCountryById" resultMap="countryMapper">
        select cid,cname from country where cid = #{cid}
    </select>
    •  测试

  • 多对一关联查询
      • 实体

    •  多对一通过多表连接查询实现
<?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="com.ryanxu.dao.IMinisterDao">
    <resultMap type="Minister" id="MinisterMapper">
        <id column="mid" property="mid" />
        <result column="mname" property="mname" />
        <association property="country" javaType="Country">
            <id column="cid" property="cid" />
            <result column="cname" property="cname" />
        </association>
    </resultMap>
    <select id="selectMinisterById" resultMap="MinisterMapper">
        select mid,mname,cid,cname
        from minister join country on minister.countryId = cid
        where mid = #{mid}
    </select>
</mapper>
  •  测试

  •  多对一通过多表单独查询方式实现
    <select id="selectCountryById" resultType="Country">
        select cid,cname from country where cid = #{cid}
    </select>
    <resultMap type="Minister" id="MinisterMapper">
        <id column="mid" property="mid"/>
        <result column="mname" property="mname"/>
        <association property="country"
                     javaType="Country"
                     select="selectCountryById"
                     column="countryId"/>
    </resultMap>
    <select id="selectMinisterById" resultMap="MinisterMapper">
        select mid,mname,countryId from minister where mid = #{mid}
    </select>
  • 测试

  • 自关联查询

    (1)自关联的DB表

 

    (2)以一对多方式处理

      (A)查询指定栏目的所有子孙栏目

<?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="com.ryanxu.dao.INewsLableDao">
<!--     <select id="selectChildrenByParent" resultMap="newslabelMapper">
          select id,name from newslabel where pid = #{pid}
      </select> -->
      <resultMap id ="newslabelMapper" type="NewsLabel">
          <id column="id" property="id"/>
          <result column="name" property="name"/>
          <collection property="children"
                      ofType="NewsLabel"
                      select="selectChildrenByParent"
                      column="id"/>
      </resultMap>
      <select id="selectChildrenByParent" resultMap="newslabelMapper">
          select id,name from newslabel where pid = #{pid}
      </select>
  </mapper>

      (B)查询指定栏目及其所有子孙栏目

      <select id="selectChildrenByParent" resultMap="newslabelMapper">
          select id,name from newslabel where pid=#{pid}
      </select>
      <resultMap id ="newslabelMapper" type="NewsLabel">
          <id column="id" property="id"/>
          <result column="name" property="name"/>
          <collection property="children"
                      ofType="NewsLabel"
                      select="selectChildrenByParent"
                      column="id"/>
      </resultMap>
      
      <select id="selectNewsLabelById" resultMap="newslabelMapper">
          select id,name from newslabel where id = #{id}
      </select>

 

    (3)以多对一方式处理(查询当前栏目和所有的父栏目)

 

      <resultMap id ="newslabelMapper" type="NewsLabel">
          <id column="id" property="id"/>
          <result column="name" property="name"/>
          <association property="parent"
                       javaType="NewsLabel"
                       select="selectNewsLabelById"
                       column="pid"/>
      </resultMap>
      
      <select id="selectNewsLabelById" resultMap="newslabelMapper">
          select id,name,pid from newslabel where id = #{id}
      </select>
  • 多对多关联查询
    • 实体类

 

<?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="com.ryanxu.dao.IStudentDao">
    <resultMap id="studentMapper" type="Student">
        <id column="sid" property="sid" />
        <result column="sname" property="sname" />
        <collection property="cources" ofType="Course">
            <id column="cid" property="cid" />
            <result column="cname" property="cname" />
        </collection>

    </resultMap>
    <select id="selectStudentById" resultMap="studentMapper">
        select sid,sname,cid,cname
        from student join sc on student.sid = sc.studentId join course on
        sc.courseId = course.cid
        where sid = #{sid}
    </select>
</mapper>

 2.关联查询

  • 概念:Mybatis中的延迟加载,也称为懒加载,是指在进行关联查询时,按照设置延迟规则推迟对关联对象的select查询。延迟加载可以有效地减少数据库压力。需要注意的是,Mybatis的延迟加载只是对关联对象的查询有延迟设置,对于主加载对象都是直接执行查询语句的。
  • 加载时机

    直接加载:执行完对主加载对象的select语句,马上执行对关联对象的select查询。

    侵入式延迟:执行对主加载对象的查询时,不会执行对关联的查询。但当要访问主加载对象的详情时,就会马上执行关联对象的select查询。即对关联对象的查询执行,侵入到了主加载对象的详情访问中。也可以这样理解:将关联对象的详情侵入到了主加载对象          的详情中,即将关联对象的详情作为主加载对象的详情的一部分出现了。

    深度延迟:执行对主加载对象的查询时,不会执行对关联对象的查询。访问主加载对象的详情时也不会执行关联对象的select查询。只有当真正访问关联对象的详情时,才会执行对关联对象的select查询。

    需要注意的是,延迟加载的应用要求,关联对象的查询与主加载对象的查询必须是分别进行的select语句,不能是使用多表连接所进行的select查询。因为,多表连接查询,其实质是对一张表的查询,对由多个表连接后形成的一张表的查询。会一次性将多张表的           所有信息查询出来。

  • 加载配置

    延迟加载配置放在settings标签下 settings在properties之后

    延迟加载的总开关是 lazyLoadingEnabled 默认是false 这种情况下就是直接加载

    侵入式加载的开关是 aggressiveLazyLoading 默认是true 所以只要将总开关打开 就是侵入式加载了

    将侵入式加载的开关关掉 false 那么就是深度延迟了

    <!-- 设置整个应用所使用的常量 -->
    <settings>
        <!-- 延迟加载的总开关 -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!-- 侵入式延迟加载开关 -->
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>

 

猜你喜欢

转载自www.cnblogs.com/windbag7/p/9368074.html