10.关联关系查询

关联关系查询

当查询内容涉及到具有关联关系的多个表时,就需要使用关联查询

根据表与表间的关联关系的不同,关联查询分为四种:

(1)一对一关联查询

(2)一对多关联查询

(3)多对一关联查询

(4)多对多关联查询

由于日常工作中最常见的关联关系是一对多、多对一与多对多,所以这里就不专门只讲

解一对一关联查询了,其解决方案与多对一解决方案是相同的。

1.一对多关联查询

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

A、多表连接查询方式(一条SQL语句):

 1 <mapper namespace="com.mybatis.dao.CountryDAO" >
 2 <!-- parameterType 可以省略 -->
 3
 4     <resultMap type="Country" id="countryMapper">
 5     <!-- 和解决字段名和属性名不相同的问题 不同,在这里,就算属性名和数据库中的字段名一致,也要写出来,不会主动帮你填入的 -->
 6         <id column="cid" property="cid"/>
 7         <result column="cname" property="cname"/>
 8         <!-- 一对多,一的一方存储了多的一方,以集合的形式,collection标签可以帮助我们完成 集合里面对象的构成 -->
 9         <collection property="ministers" ofType="Minister">
10         <id column="mid" property="mid"/>
11         <result column="mname" property="mname" />
12         </collection>
13     </resultMap>
14
15
16     <!-- 多表连接查询方式,这种方式 无法进行延迟加载,多的一方直接跟着 一的一方一起查出来了,会消耗很多资源 -->
17     <select id="selectCountryById" resultMap="countryMapper">
18     <!-- 查询出了这四个字段,但是这四个字段是无法直接构成country对象的 ,故使用resultMap,让其将mid,mname构成ministers,再构成country-->
19         select cid,cname,mid,mname from country,minister where countryId = cid and cid = #{cid}
20     </select>
22 </mapper>

  在映射文件中使用 <collection/>标签体现出两个实体对象间的关联关系。其两个属性的意义位:

  property:指定关联类型,即Country类中的集合类型

  ofType:集合属性的泛型类型

B、多表单独查询方式(多条SQL语句)

多表连接查询方式是将多张表进行连接,连为一张表后进行查询。其查询的本质是一张表。

而多表单独查询方式是多张表各自查询各自的相关内容,需要多张表的联合数据了,

则 将主表的查询结果联合其它表的查询结果,封装为一个对象。

当然,这多个查询是可以跨越多个映射文件的,即是可以跨越多个 namespace 的。

在 使用其它 namespace 的查询时,添加上其所在的 namespace 即可

 1 <mapper namespace="com.mybatis.dao.CountryDAO" >
 2
 3     <resultMap type="Country" id="countryMapper">
 4         <id column="cid" property="cid"/>
 5         <result column="cname" property="cname"/>
 6         <!-- 执行到这里时,会调用 select 属性中的 SQL,column 作为外键参数,cid-->
 7         <collection property="ministers" ofType="Minister" select="selectMinisterByCountry" column="cid">
 8         </collection>
 9     </resultMap>
10
11     <!-- 使用多表单独查询的方式(使用多条SQL语句) 采用这种方式,可以实现延迟加载-->
12     <!-- 由DAO调用,故先执行 selectCountryById ,执行到collection,这时需要 执行 selectMinisterByCountry -->
13     <select id="selectCountryById" resultMap="countryMapper">
14         select cid,cname from country where cid = #{cid}
15     </select>
16     <select id="selectMinisterByCountry" resultType="Minister">
17          select mid,mname from minister where countryId = #{countryId}
18     </select>
19
20 </mapper>

关联属性<collection/>的数据来自于另一个查询<selectMinisterByCountry/>。

而该查询<selectMinisterByCountry/>的动态参数 countryId=#{ooo}的值来自于查询<selectCountryById/>的查询结果字段 cid

2.多对一关联查询

在查询多方对象的时候,同时将其所关联的一方对象也查 询出来。

由于在查询多方对象时也是一个一个查询,所以多对一关联查询,其实就是一对一关联查询

即一对一关联查询的实现方式与多对一的实现方式是相同的

 1 <mapper namespace="com.mybatis.dao.MinisterDAO" >
 2 <!-- parameterType 可以省略 -->
 3
 4     <resultMap type="Minister" id="ministerMapper">
 5     <!-- 和解决字段名和属性名不相同的问题 不同,在这里,就算属性名和数据库中的字段名一致,也要写出来,不会主动帮你填入的 -->
 6         <id column="mid" property="mid"/>
 7         <result column="mname" property="mname"/>
 8
 9         <!-- 多对一采用的是 association 来完成关联属性的构成 -->
10         <association property="country" javaType="Country">
11             <id column="cid" property="cid"/>
12             <result column="cname" property="cname"/>
13         </association>
14     </resultMap>
15
16
17     <!-- 多表连接查询方式,这种方式 无法进行延迟加载,多的一方直接跟着 一的一方一起查出来了,会消耗很多资源 -->
18     <select id="selectMinisterById" resultMap="ministerMapper">
19         select mid,mname,cid,cname from minister,country where mid = #{mid} and countryId = cid
20     </select>
21
22 </mapper>

注意:在映射文件中使用 <association/> 标签体现出两个实体对象间的关联关系

  property:指定关联属性,即Minister类中的 country属性

  javaType:关联属性的类型

多表单独查询的方式

 1 <mapper namespace="com.mybatis.dao.MinisterDAO" >
 2 <!-- parameterType 可以省略 -->
 3
 4     <resultMap type="Minister" id="ministerMapper">
 5     <!-- 和解决字段名和属性名不相同的问题 不同,在这里,就算属性名和数据库中的字段名一致,也要写出来,不会主动帮你填入的 -->
 6         <id column="mid" property="mid"/>
 7         <result column="mname" property="mname"/>
 8
 9         <!-- 多对一采用的是 association 来完成关联属性的构成 -->
10         <association property="country" javaType="Country" select="selectCountryById" column="countryId">
11             <id column="cid" property="cid"/>
12             <result column="cname" property="cname"/>
13         </association>
14     </resultMap>
15
16
17     <!-- 使用多表单独查询的方式(使用多条SQL语句) 采用这种方式,可以实现延迟加载-->
18     <select id="selectMinisterById" resultMap="ministerMapper">
19         select mid,mname,countryId from minister where mid = #{mid}
20     </select>
21
22     <select id="selectCountryById" resultType="Country">
23         select cid,cname from country where cid = #{countryId}
24     </select>
25
26 </mapper>

3.自关联查询

所谓自关联是指,自己即充当一方,又充当多方,是 1:n 或 n:1 的变型

例如,对于新闻栏目 NewsColumn,可以充当一方,即父栏目,也可以充当多方,即子栏目。而反映到 DB 表中,只有一张表,这张表中具有一个外键,用于表示该栏目的父栏目。一级栏目没有父栏 目,所以可以将其外键值设为 0,而子栏目则具有外键值。

为了便于理解,将自关联分为两种情况来讲解。一种是当作 1:n 讲解,即当前类作为一 方,其包含多方的集合域属性。一种是当作 n:1 讲解,即当前类作为多方,其包含一方的域 属性。

下面以新闻栏目为例进行讲解。由于 Column 是 DBMS 中的关键字,为了避免误解,将 新闻栏目实体类定义为 NewsLabel。

以一对多方式处理:

   以一对多方式处理,即一方可以看到多方。该处理方式的引用场景比较多,例如在页面上点击父栏目,显示出其子栏目

A、查询指定栏目的所有子孙栏目:

 1 <mapper namespace="com.mybatis.dao.NewsLabelDAO" >
 2
 3 <!-- 自关联查询 -->
 4
 5     <resultMap type="NewsLabel" id="newsLabelMapper">
 6         <id property="id" column="id"/>
 7         <result property="name" column="name"/>
 8         <!-- pid动态参数值 来自上一次查询的结果的 id 值 -->
 9         <collection property="chirldren" ofType="NewsLabel" select="selectChildrenByParentId" column="id"/>
10
11     </resultMap>
12
13     <!-- select 语句的递归调用  -->
14     <!-- 过程:1.先查到 3,4是2 的 子元素
15                2.深度优先,从3开始下手,在构造3的chirldren属性时,需要去查3下面是否有子元素(因为collection中 使用的select 语句是selectChildrenByParentId)
16                     这就构成了递归,如果3下面有子元素,则再递归着去查这个子元素下面是否还要子元素
17
18     -->
19     <select id="selectChildrenByParentId" resultMap="newsLabelMapper">
20         select id,name from newslabel where pid = #{pid}
21     </select>
22
23
24 </mapper>

B、查询指定栏目及其所有子孙栏目:

这里的查询结果,即要包含指定 id 的当前栏目,还包含其所有辈份的孙子栏目。

即给 出的 id 实际为当前要查询的栏目的 id。

 1 <!-- 自关联查询 -->
 2     <resultMap type="NewsLabel" id="newsLabelMapper">
 3         <id property="id" column="id"/>
 4         <result property="name" column="name"/>
 5         <!-- pid动态参数值 来自上一次查询的结果的 id 值 -->
 6         <collection property="chirldren" ofType="NewsLabel" select="selectChildrenByParent" column="id"/>
 7
 8     </resultMap>
 9
10     <!-- 1.先根据查出 查出对应的 NewsLabel -->
11     <select id="selectNewsLabelById" resultMap="newsLabelMapper">
12         select id,name from newslabel where id = #{id}
13     </select>
14
15     <!-- 2.再根据前一次出的id 作为 pid,查询这个id 下所有的子元素 -->
16     <select id="selectChildrenByParent" resultMap="newsLabelMapper">
17         select id,name from newslabel where pid = #{id}
18     </select>
19
20
21
22
23 </mapper>

以多对一方式处理:

  以多对一方式处理,即多方可以看到一方

 1 <!-- 自关联查询 -->
 2
 3     <resultMap type="NewsLabel" id="newsLabelMapper">
 4         <id property="id" column="id"/>
 5         <result property="name" column="name"/>
 6         <!-- pid动态参数值 来自上一次查询的结果的 id 值 -->
 7         <association property="parent" javaType="NewsLabel" select="selectParentByParentId" column="pid"/>
 8
 9     </resultMap>
10
11     <select id="selectParentByParentId" resultMap="newsLabelMapper">
12         select id,name,pid from newslabel where id = #{pid}
13     </select>
14
15
16 </mapper>

4.多对多关联查询

什么是多对多关联关系?一个学生可以选多门课程,而一门课程可以由多个学生选。这就是典型的多对多关系关系。

所以,所谓多对多关系,其实是由两个互反的一对多关系组成。

一般情况下,多对多关系都会通过一个中间表来建立,例如选课表。

多对多关联关系也是通过映射文件<resultMap/>的<cooection/>体现的

但是,需要注意的是SQL语句中是对三张表的连接查询

 1 <!-- 多对多查询 -->
 2
 3     <resultMap type="Student" id="studentMapper">
 4         <id property="sid" column="sid"/>
 5         <result property="sname" column="sname"/>
 6         <collection property="courses" ofType="Course" >
 7             <id property="cid" column="cid"/>
 8             <result property="cname" column="cname"/>
 9         </collection>
10
11     </resultMap>
12
13     <select id="selectStudentById" resultMap="studentMapper">
14         select sid,sname,cid,cname from student,course,middle where sid = studentId and cid = courseId and sid = #{sid}
15     </select>
时间: 2024-08-27 15:58:31

10.关联关系查询的相关文章

3、Hibenrate中HQL的10中查询方式

二.具体事例如下: 2.0 编写如下sql语句 1 create table teacher(tid number not null primary key,tname varchar2(20)); 2 create sequence seq_teacher; 3 insert into teacher values(seq_teacher.nextval,'holly'); 4 insert into teacher values(seq_teacher.nextval,'石头'); 5 co

怎样从10亿查询词找出出现频率最高的10个

转自:http://dongxicheng.org/big-data/select-ten-from-billions/ 1. 问题描述 在大规模数据处理中,常遇到的一类问题是,在海量数据中找出出现频率最高的前K个数,或者从海量数据中找出最大的前K个数,这类问题通常称为“top K”问题,如:在搜索引擎中,统计搜索最热门的10个查询词:在歌曲库中统计下载率最高的前10首歌等等. 2. 当前解决方案 针对top k类问题,通常比较好的方案是[分治+trie树/hash+小顶堆],即先将数据集按照h

mybatis学习笔记(10)-一对一查询

mybatis学习笔记(10)-一对一查询 mybatis学习笔记10-一对一查询 resultType实现 resultMap实现 resultType和resultMap实现一对一查询小结 本文使用两种方式(resultType和resultMap)实现一对一查询,查询订单信息,关联查询创建订单的用户信息 resultType实现 sql语句 确定查询的主表:订单表 确定查询的关联表:用户表 关联查询使用内连接?还是外连接? 因为orders表中有一个外键(user_id),通过外键关联查询

Hibernate学习10——Hibernate 查询方式

本章主要是以查询Student的例子: Student.java: package com.cy.model; public class Student { private int id; private String name; private int age; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name;

hibernate关联关系查询

关联关系 一对一 A中包含B的对象,B中包含A的对象 一对多 A中包含B的集合,B中包含A的对象 多对多 A中包含B的集合,B中包含A的集合 1,一对多配置 一名老师可以对应多名学生 2,模型类 老师类中包含学生的集合(通常可以将集合直接进行初始化) 学生类中包含老师的对象 3,配置 1 TeacherModel.hbm.xml(教师) 2 <hibernate-mapping package="cn.itcast.h3.realtion.one2many.vo" > 3

MVC5 + EF6 + Bootstrap3 (10) 数据查询页面

文章来源:Slark.NET-博客园 http://www.cnblogs.com/slark/p/mvc5-ef6-bs3-get-started-search-page.html 上一节:MVC5 + EF6 + Bootstrap3 (9) HtmlHelper用法大全(下) 源码下载:点我下载 目录 前言 创建Model 创建数据库上下文DbContext 创建初始化数据 创建Controller 创建View 查看结果页面 查看数据库 结尾 前言 前面铺垫了那么多,今天我们就用MVC5

【sqli-labs】 less54 GET -Challenge -Union -10 queries allowed -Variation1 (GET型 挑战 联合查询 只允许10次查询 变化1)

尝试的次数只有10次 http://192.168.136.128/sqli-labs-master/Less-54/index.php?id=1' 单引号报错,错误信息没有显示 加注释符页面恢复正常,判断为单引号闭合 http://192.168.136.128/sqli-labs-master/Less-54/index.php?id=1'%23 通过页面信息可以判断查询的表至少有id,username,password三个字段,所以union select至少应该select3个字段 ht

【MySQL】【10】查询某年,某季度,某月,某周,某天的数据

前言: 1,某年 2,某季度 3,某月 4,某周 5,某天 正文: 1,某年 select * from table where created like '2018-%'; select * from table where left(created, 4) = '2018'; select * from table where year(created) = '2018'; 今年的数据 select * from table where year(created) = year(now())

10.模糊查询

---带条件的查询--- --语法:select 字段列表/* from 表列表where 条件.. select * from Student where ClassId=1 or ClassId=2 or ClassId=3 --使用in代表一个具体的值范围,in要求指定的范围的数据类型一致 select * from Student where ClassId in(1,2,3) select * from Student where ClassId not in(1,2,3) --所谓类