关于一对多,多对多的多表查询的控制

一、一对多

以班级Classes和学生Student为例:

回忆sql语句:

//内链接,两种方式效果一样,查询的是两边都有的数据

SELECT c.*,s.* FROM classes c,student s WHERE s.cid=c.cid;

SELECT c.cname,s.sname FROM classes c INNER JOIN student s ON s.cid=c.cid;

//左外连接,在内链接基础上,左边表有而右边表没有,两种方式等效;
SELECT c.* ,s.* FROM student s LEFT OUTER JOIN classes c ON s.cid=c.cid;
SELECT c.* ,s.* FROM student s LEFT  JOIN classes c ON s.cid=c.cid;

//右外连接,在内链接基础上,右边有而左边无,两种方式等效;
SELECT c.* ,s.* FROM classes c RIGHT  OUTER JOIN student s ON s.cid=c.cid;
SELECT c.* ,s.* FROM classes c RIGHT  JOIN student s ON s.cid=c.cid;

HQL语句:

//查询所有:

from Classes c,Student s where c.cid=s.classes.cid;

//选择某些属性查询

select c.cname,s.sname from Classes c,Student s where c.cid=s.classes.cid;

//选择某些属性,封装为bean查询;

select new cn.itheima03.hibernate.domain.ClassesView(c.cname,s.sname)  from Classes c,Student s where c.cid=s.classes.cid;

//内链接查询,得到的是两个bean

from Classes c inner join c.students s;

//内敛链接查询,得到的是Classes对象,对象中包含studet集合

from Classes c inner join fetch c.students s;

from Student s inner join fetch s.classes c;

select new cn.itheima03.hibernate.domain.ClassesView(c.cname,s.sname)  from Student s inner join  s.classes c ;

from Classes c left outer join fetch c.students s;

from Student s left outer join fetch s.classes;

示例代码:


/**

* 1.一对多

* sql:select c.*,s.* from classes c,student s where c.cid=s.cid;

* hql:from Classes c,Student s where c.cid=s.classes.cid,注意与上句的区别;

* 得到的list是object[],数组中的元素是Classes和Student对象;

*

*/

@Test

public void testOneToMany_EQ(){

Session   session = sessionFactory.openSession();

Query query = session.createQuery( "from Classes c,Student s where c.cid=s.classes.cid");

List list = query.list();

System. out.println(query.list().size());

session.close();

}

/**

* 2.带属性的查询;

* list中装的是object[];

*/

@Test

public void testOneToMany_EQ_Property(){

Session   session = sessionFactory.openSession();

Query query = session.createQuery( "select c.cname,s.sname from Classes c,Student s where c.cid=s.classes.cid");

query.list();

session.close();

}

/**

* 3.带属性查询,将查询结果封装成一个bean;

* 得到的list中装的是classView对象;

*/

@Test

public void testOneToMany_EQ_Property_Constructor(){

Session   session = sessionFactory.openSession();

Query query = session.createQuery( "select new cn.itheima03.hibernate.domain.ClassesView(c.cname,s.sname) " +

"from Classes c,Student s where c.cid=s.classes.cid");

List list = query.list();

session.close();

}

/**

* 4.内连接

* 结果与例子1一样;

*/

@Test

public void testOneToMany_InnerJoin_Query(){

Session   session = sessionFactory.openSession();

StringBuffer buffer = new StringBuffer();

buffer.append( "from Classes c inner join c.students s");

Query query = session.createQuery(buffer.toString());

query.list();

session.close();

}

/**

* 5.迫切内连接1:获取所有有学生的班级及班级下的学生;

* 要想得到的集合中装的Classes对象,对象中set集合中装student,可以使用迫切内链接。

*

*/

@Test

public void testOneToMany_InnerJoin_Fetch_Query_1(){

Session   session = sessionFactory.openSession();

StringBuffer buffer = new StringBuffer();

buffer.append( "from Classes c inner join fetch c.students s");

Query query = session.createQuery(buffer.toString());

List list = query.list();

session.close();

}

/**

* 6.迫切内连接2

* 从学生端出发;

*/

@Test

public void testOneToMany_InnerJoin_Fetch_Query_2(){

Session   session = sessionFactory.openSession();

StringBuffer buffer = new StringBuffer();

buffer.append( "from Student s inner join fetch s.classes c");

Query query = session.createQuery(buffer.toString());

query.list();

session.close();

}

/**

* 7.迫切内连接3:获取属性,封装结果;

* select new cn.itheima03.hibernate.domain.ClassView(c.cname,s.sname)

*   from Student s inner join fetch s.classes c;

* 上述的 hql语句会报错,因为from后面想要的结构和select想要的结构是冲突的,所以

如果在from后面加fetch,不能写select语句,如果加select,不能写fetch,两者只能选择其一

*

*/

@Test

public void testOneToMany_InnerJoin_Fetch_Query_Property(){

Session   session = sessionFactory.openSession();

StringBuffer buffer = new StringBuffer();

//下面的写法不对;

//        buffer.append("select new cn.itheima03.hibernate.domain.ClassView(c.cname,s.sname) " +

//                 " from Student s inner join fetch s.classes c");

//不要fetch;

buffer.append( "select new cn.itheima03.hibernate.domain.ClassesView(c.cname,s.sname)  " +

"  from Student s inner join  s.classes c " );

Query query = session.createQuery(buffer.toString());

List list = query.list();

session.close();

}

/**

* 8.迫切左外连接

* 从班级出发,得到班级对应的学生

*/

@Test

public void testOneToMany_LeftJoin_Fetch(){

Session   session = sessionFactory.openSession();

StringBuffer buffer = new StringBuffer();

buffer.append( "from Classes c left outer join fetch c.students s");

Query query = session.createQuery(buffer.toString());

List<Classes> list = query.list();

for (Classes classes : list) {

System. out.println("classes:" +classes.getCname());

Set<Student> students = classes.getStudents();

for (Student student : students) {

System. out.println("     student:" +student.getSname());

}

}

session.close();

}

/**

* 9.迫切左外连接2

* 从学生出发,得到对应的班级

*/

@Test

public void testOneToMany_RightJoin_Fetch(){

Session   session = sessionFactory.openSession();

StringBuffer buffer = new StringBuffer();

buffer.append( "from Student s left outer join fetch s.classes ");

Query query = session.createQuery(buffer.toString());

List<Student> list = query.list();

for (Student student : list) {

System. out.println("student:" +student.getSname());

if (student.getClasses()!=null) {

System. out.println("     " +student.getClasses().getCname());

}

}

session.close();

}

二。多对多

学生Student和课程Course为例:

Student里有装Course的set集合,Course里也有装Student的set集合;

多对多与一对多操作差不多


     /**

* 1.得到所有的学生以及其对应的课程

* 从学生端出发

* list装的是学生;

*/

@Test

public void testManyToMany_LeftJoin_Fecth(){

Session   session = sessionFactory.openSession();

StringBuffer buffer = new StringBuffer();

buffer.append( "from Student s left outer join fetch s.courses");

Query query = session.createQuery(buffer.toString());

List list = query.list();

session.close();

}

/**

* 2.得到所有的课程及课程下对应的学生;

* list装的是课程

*/

@Test

public void testManyToMany_LeftJoin_Fecth_2(){

Session   session = sessionFactory.openSession();

StringBuffer buffer = new StringBuffer();

buffer.append( "from Course c left outer join fetch c.students s");

Query query = session.createQuery(buffer.toString());

query.list();

session.close();

}

/**

* 3.一对多和多对多的结合

* 得到所有班级下的所有学生以及所有学生下的所有课程;

* 从班级出发

*/

@Test

public void testManyToManyAndOneToMany(){

Session   session = sessionFactory.openSession();

StringBuffer buffer = new StringBuffer();

buffer.append( "from Classes c left outer join fetch" +

" c.students s left outer join fetch s.courses");

Query query = session.createQuery(buffer.toString());

List<Classes> classeList = query.list();

//去掉集合中的重复元素

Set<Classes> sets = new HashSet<Classes>(classeList);

classeList = new ArrayList<Classes>(sets);

System. out.println(classeList.size());

for(Classes classes:classeList){//遍历班级

System. out.println(classes.getCname());

Set<Student> students = classes.getStudents();//得到班级下的学生

for(Student student:students){//遍历学生

System. out.println(student.getSname());

Set<Course> courses = student.getCourses();

for(Course course:courses){//遍历学生下的课程

System. out.println(course.getCname());

}

}

}

session.close();

}

/**

* 从中间表出发,班级有学生,学生修课程,故从学生角度出发进行查询;

*/

@Test

public void testManyToManyAndOneToMany_2(){

Session   session = sessionFactory.openSession();

StringBuffer buffer = new StringBuffer();

buffer.append( "from Student s left outer join fetch s.classes c

left outer join fetch s.courses cc");

Query query = session.createQuery(buffer.toString());

List<Student> studentList = query.list();

for(Student student:studentList){

System. out.println(student.getSname());

Classes classes = student.getClasses();

System. out.println(classes.getCname());

Set<Course> courses = student.getCourses();

for(Course course:courses){

System. out.println(course.getCname());

}

}

session.close();

}

/*******************************************************************************/

/**

* 面向对象的查询

*/

@Test

public void testQueryCriteria(){

Session   session = sessionFactory.openSession();

List<Classes>  classesList = session.createCriteria(Classes.class).list() ;

System. out.println(classesList.size());

session.close();

}

@Test

public void testQueryCriteria_Where(){

Session   session = sessionFactory.openSession();

Classes classes = (Classes)session.createCriteria(Classes.class).add(Restrictions.eq("cid" , 1L)).uniqueResult();

System. out.println(classes.getCname());

session.close();

}

}

总结:

无论是一对多还是多对多,hql语句中含有fetch时,得到的list装的是From 后面的对象,对象中可能有相关联对象的集合或者对象;

时间: 2024-10-13 22:33:11

关于一对多,多对多的多表查询的控制的相关文章

MyBatis 多表查询

1.多表设计 多表查询 a.多表设计 (1)一对一 在任意一方设计外键保存另一张表的主键,维系表和表的关系 (2)一对多 在多的一方设计外键保存一的一方的主键,维系表和表的关系 (3)多对多 设计一张第三方关系表,存储两张表的主键的对应关系,将一个多对多拆成两个一对多来存储 b.多表查询 笛卡尔积查询 内连接查询 外连接查询 左外连接查询 右外连接查询 全外连接查询 2.MyBatis中的一对一查询 create table room(id int primary key,name varcha

多表查询总结

多表查询 一.创建数据库 from django.db import models # Create your models here. """ 你在写orm语句的时候 跟你写sql语句一样 不要想着一次性写完 写一点查一点看一点 """ class Book(models.Model): """ 1. 一本书对应一个出版社,出版社与书,一对多关系, 2. 一本书可以多个作者,一个作者可出多本说 作者与书 多多的关系

django(3) 一对多跨表查询、多对多

1.一对多跨表查询获取数据的三种形式:对象.字典.元组 例:有host与business两张表,host与business的id字段关联,business在host表中的对象名是b,  通过查询host表获取的querySet中的b来查询business表. 以下两种方式都是操作host表: a.以对象的形式跨表查询,查询business表的数据:row.b.caption,row.b.id b.以字典和元组的形式跨表查询,查询business表的数据,跨表查询的时候要用双下划线  'b__id

hibernate 一对多|多对一

一对多:(一个客户对应多个联系人) 客户实体:Customer.java package cn.future.domain; import java.util.HashSet; import java.util.Set; public class Customer { /* * CREATE TABLE `cst_customer` ( `cust_id` BIGINT(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)', `cust_name` VAR

框架 day32 Hibernate,一级缓存,关联关系映射(一对多,多对多)

一级缓存 概念 *在 Session 接口的实现中包含一系列的 Java 集合, 这些 Java集合构成了Session缓存. 只要 Session 实例没有结束生命周期, 存放在它缓存中的对象也不会结束生命周期 *当session的save()方法持久化一个对象时,该对象被载入缓存, 以后即使程序中不再引用该对象,只要缓存不清空,该对象仍然处于生命周期中. 当试图get(). load()对象时,会判断缓存中是否存在该对象,有则返回,此时不查询数据库.没有再查询数据库 *Session 能够在

Django一对多,多对多操作

简要说明 Django里面的数据库操作O2O&M2M,一般归属于models管理 使用场景 一对一:在某表中创建一行数据时,有一个单选的下拉框(下拉框中的内容被用过一次就消失了).//两个表的数据一一对应 例如:原有含10列数据的一张表保存相关信息,经过一段时间之后,10列无法满足需求,需要为原来的表再添加5列数据. 一对多:当一张表中创建一行数据时,有一个单选的下拉框(可以被重复选择).//表1的数据可以在表2里面重复出现 例如:创建用户信息时候,需要选择一个用户类型[普通用户][金牌用户][

SQLAlchemy_定义(一对一/一对多/多对多)关系

目录 Basic Relationship Patterns One To Many One To One Many To Many Basic Relationship Patterns 基本关系模式 The imports used for each of the following sections is as follows: 下列的 import 语句,应用到接下来所有的代章节中: from sqlalchemy import Table, Column, Integer, Forei

DjangoORM一对多&多对多操作

简要说明 通过操作对象的方式操作数据库 详细步骤 models.py的结构是: 如果models.py中外键定义没有写 related_name='student_teacher', 可以直接用 studentList = teacher.student_teacher.all() 可以改写成: teacher = Teacher.objects.get(id = 1) studentList = teacher.student_set.all() =======================

Hibernate 集合映射 一对多多对一 inverse属性 + cascade级联属性 多对多 一对一 关系映射

1 . 集合映射 需求:购物商城,用户有多个地址. // javabean设计 // javabean设计 public class User { private int userId; private String userName; // 一个用户,对应的多个地址 private Set<String> address; private List<String> addressList = new ArrayList<String>(); //private Str