hibernate 一对多和多对一查询

2024-05-01 09:58
文章标签 查询 hibernate 一对

本文主要是介绍hibernate 一对多和多对一查询,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、一对多
以班级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;


示例代码:
如果加select,不能写fetch,两者只能选择其一
/**
      * 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 后面的对象,对象中可能有相关联对象的集合或者对象;

这篇关于hibernate 一对多和多对一查询的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/951380

相关文章

Mybatis 传参与排序模糊查询功能实现

《Mybatis传参与排序模糊查询功能实现》:本文主要介绍Mybatis传参与排序模糊查询功能实现,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、#{ }和${ }传参的区别二、排序三、like查询四、数据库连接池五、mysql 开发企业规范一、#{ }和${ }传参的

浅谈mysql的sql_mode可能会限制你的查询

《浅谈mysql的sql_mode可能会限制你的查询》本文主要介绍了浅谈mysql的sql_mode可能会限制你的查询,这个问题主要说明的是,我们写的sql查询语句违背了聚合函数groupby的规则... 目录场景:问题描述原因分析:解决方案:第一种:修改后,只有当前生效,若是mysql服务重启,就会失效;

MySQL多列IN查询的实现

《MySQL多列IN查询的实现》多列IN查询是一种强大的筛选工具,它允许通过多字段组合快速过滤数据,本文主要介绍了MySQL多列IN查询的实现,具有一定的参考价值,感兴趣的可以了解一下... 目录一、基础语法:多列 IN 的两种写法1. 直接值列表2. 子查询二、对比传统 OR 的写法三、性能分析与优化1.

mybatis-plus 实现查询表名动态修改的示例代码

《mybatis-plus实现查询表名动态修改的示例代码》通过MyBatis-Plus实现表名的动态替换,根据配置或入参选择不同的表,本文主要介绍了mybatis-plus实现查询表名动态修改的示... 目录实现数据库初始化依赖包配置读取类设置 myBATis-plus 插件测试通过 mybatis-plu

MySQL中实现多表查询的操作方法(配sql+实操图+案例巩固 通俗易懂版)

《MySQL中实现多表查询的操作方法(配sql+实操图+案例巩固通俗易懂版)》本文主要讲解了MySQL中的多表查询,包括子查询、笛卡尔积、自连接、多表查询的实现方法以及多列子查询等,通过实际例子和操... 目录复合查询1. 回顾查询基本操作group by 分组having1. 显示部门号为10的部门名,员

mysql关联查询速度慢的问题及解决

《mysql关联查询速度慢的问题及解决》:本文主要介绍mysql关联查询速度慢的问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录mysql关联查询速度慢1. 记录原因1.1 在一次线上的服务中1.2 最终发现2. 解决方案3. 具体操作总结mysql

mysql线上查询之前要性能调优的技巧及示例

《mysql线上查询之前要性能调优的技巧及示例》文章介绍了查询优化的几种方法,包括使用索引、避免不必要的列和行、有效的JOIN策略、子查询和派生表的优化、查询提示和优化器提示等,这些方法可以帮助提高数... 目录避免不必要的列和行使用有效的JOIN策略使用子查询和派生表时要小心使用查询提示和优化器提示其他常

SQL 中多表查询的常见连接方式详解

《SQL中多表查询的常见连接方式详解》本文介绍SQL中多表查询的常见连接方式,包括内连接(INNERJOIN)、左连接(LEFTJOIN)、右连接(RIGHTJOIN)、全外连接(FULLOUTER... 目录一、连接类型图表(ASCII 形式)二、前置代码(创建示例表)三、连接方式代码示例1. 内连接(I

轻松上手MYSQL之JSON函数实现高效数据查询与操作

《轻松上手MYSQL之JSON函数实现高效数据查询与操作》:本文主要介绍轻松上手MYSQL之JSON函数实现高效数据查询与操作的相关资料,MySQL提供了多个JSON函数,用于处理和查询JSON数... 目录一、jsON_EXTRACT 提取指定数据二、JSON_UNQUOTE 取消双引号三、JSON_KE

查询SQL Server数据库服务器IP地址的多种有效方法

《查询SQLServer数据库服务器IP地址的多种有效方法》作为数据库管理员或开发人员,了解如何查询SQLServer数据库服务器的IP地址是一项重要技能,本文将介绍几种简单而有效的方法,帮助你轻松... 目录使用T-SQL查询方法1:使用系统函数方法2:使用系统视图使用SQL Server Configu