HQL之多表查询(一对多和多对多)

Java 里 Hibernate 的多表关联查询实战 本文旨在为 Java 开发者提供全面的 Hibernate 多表关联查询实战指南。实体间的各种关联关系映射不同查询方式的实现和比较关联查询的性能优化策略N+1 查询问题的解决方案复杂查询的构建技巧首先介绍 Hibernate 多表关联的基本概念和类型然后详细讲解各种关联映射的实现方式接着探讨不同查询方法的具体应用最后分析性能优化策略和实际应用案例: 对象关系映射,一种将面向对象语言中的对象与关系数据库中的表进行转换的技术实体(Entity) 阅读详情

一、一对多

以班级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.chen.system.model.ClassVsStudent(c.cname,s.sname) from Classes c,Student s where c.cid=s.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.chen.system.model.ClassVsStudent(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.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.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.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.chen.system.model.ClassVsStudent(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.chen.system.model.ClassVsStudent(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.chen.system.model.ClassVsStudent(c.cname,s.sname) " +
//                 " from Student s inner join fetch s.classes c");

           //不要fetch;
          buffer.append( "select new cn.chen.system.model.ClassVsStudent(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();
          }
}
Hibernate-HQL语句多对多写法 Hibernate 多对多HQL语句写法 立即下载

相关推荐

HQL多对多的查询语句分析

NULL 博文链接:https://tanjunxiaoge.iteye.com/blog/1750865

hql语句:一对多查询

一对多的查询又包含以下情况: 1、等值连接 2、内连接 3、迫切内连接 4、左外连接 5、迫切左外连接1、等值连接:一对多查询的时候,由于使用的hql语句,是根据类来查询的,所以hql语句这样表示: /** * 等值连接 */ public void Connect_equal(){ Session session=sessionFacto

7024

hibernate(一对多,多对一映射)操作

hibernate基于 一对多、多对一映射写的一个增加,查询,删除,修改的demo,内附数据库脚本

Spring Data JPA 的动态查询和一对多及多对多查询

1. Specifications动态查询 1.1JpaSpecificationExecutor 方法列表 T findOne(Specification spec); //查询单个对象 List findAll(Specification spec); //查询列表 //查询全部,分页 //pageable:分页参数 //返回值:分页pageBean(page:是springda...

weixin_43873712的博客 4336

GraphRAG + Ollama 本地化部署实战:从零搭建知识图谱问答系统

本文详细介绍了如何在本地部署GraphRAG与Ollama,搭建一个完全自主可控的知识图谱问答系统。通过逐步指导环境配置、项目初始化、核心设置修改以及源码适配,成功将GraphRAG从依赖云端OpenAI API转向本地Ollama服务,并选用qwen2.5:7b和nomic-embed-text模型。该方案有效解决了数据隐私与持续API成本问题,特别适合中小企业构建内部知识库或智能客服系统。

x2y3z4a5b的博客 919

别再手动建模了!用Simscape Multibody Link一键导入SolidWorks装配体到Simulink

本文介绍了如何利用Simscape Multibody Link插件将SolidWorks装配体一键导入Simulink,实现CAD到仿真的无缝衔接。该技术显著提升机械系统设计与控制效率,特别适用于工业机器人、车辆悬架等复杂机构的动力学分析。文章详细解析了插件安装、模型导出优化及仿真验证的全流程,帮助工程师摆脱手动建模的低效工作模式。

weixin_27256197的博客 461

【Hibernate九】HQL之多表查询(一对多和多对多)

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

温故而知新 4万+

Veeam Backup Replication Console 13 备份 PVE

本文介绍了如何通过Veeam Backup & Replication控制台配置与Proxmox VE(PVE)服务器的连接,包括主机地址、用户名密码和SSH信任设置。随后详细说明了部署备份Worker虚拟机的步骤,涵盖网络配置和VM创建。接着指导用户创建PVE虚拟机备份任务,包括命名、选择备份对象、存储位置、备份类型设置,以及配置备份计划任务。最后描述了备份测试执行过程,从启动备份到完成状态通知的完整流程。整个操作涉及服务器连接、Worker部署、备份配置和任务执行四个主要环节。

极致,细节 1602

Hibernate HQL 一对多查询

1、等值连接: /** * 等值查询 查询出来的结构很差 */ public List queryClasses_Student_EQ(){ Session session = sessionFactory.openSession(); List cList = session.createQuery("from Classes

快雪时晴天的专栏 1988

ptrade从零开始学量化第1期【ptrade如何新建策略、新建回测、新建交易】什么是ptrade量化交易?

回测之前需要对开始时间、结束时间、回测资金、回测基准、回测频率几个要素进行设定,设定完毕后点击保存。然后再点击回测按键,系统就会开始运行回测,回测的评价指标、收益曲线、日志都会在界面中展现。可以选择不同的业务类型(比如股票),然后给策略设定一个名称,添加成功后可以在默认策略模板基础上进行策略编写。交易界面点击新增按键进行新增交易操作,策略方案中的对象为所有策略列表中的策略,给本次交易设定名称并点击确定后系统就开始运行交易了。交易开始运行后,可以点击交易详情,查看策略评价指标、交易明细、持仓明细、交易日志。

GJ57017_wx的博客 2483

Cursor设置界面汉化保姆级教程:手把手教你修改JS文件实现中文界面(附避坑指南)

本文提供Cursor编辑器设置界面汉化的详细教程,从定位JS文件到安全修改实现中文界面,包含必备工具清单、文件路径指引和常见问题解决方案。通过手把手教学帮助用户轻松完成汉化,提升使用体验,特别适合不熟悉英文界面的开发者。

weixin_29007809的博客 1414

hql 一对多判断子表是否为空_HQL之多表查询(一对多和多对多)

/*** 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对象;**/@Testpublicv...

weixin_29185167的博客 344

小龙虾 OpenClaw 权限全攻略:轻松激活 elevated (最新版 OpenClaw 自动化任务降智、无权限、无法执行sudo等系统命令、提升 elevated 权限的解决方案)

升级小龙虾 OpenClaw 后权限不足?elevated 报错?📛 本文教你如何正确配置 OpenClaw 权限💻,让自动化任务顺利执行 🚀

XiaoqiangClub的博客 733

hql关联和连接查询实例

Hibernate提供了强大的查询系统,使用Hibernate有多种查询方法可以选择:可以使用Hibernate的HQL查询,也可以使用条件查询,甚至可以使用原生的SQL查询语句。其中HQL查询时Hibernate配置的功能强大的查询语句。HQL是非常有意识的被设计为完全面向对象的查询,它可以理解如继承、多态 和关联之类的概念。        下面我们来看一下

晨曦的专栏 2万+

路由三大分类:直连路由、静态路由、动态路由

直连路由、静态路由和动态路由各有其独特的特点和适用场景。直连路由适用于简单的直接连接网络,静态路由提供了精确的路径控制,而动态路由则在大型复杂网络中展现出强大的适应性和自动化能力。了解和掌握这三种路由类型的配置和管理,对于网络管理员来说,是确保网络高效、安全运行的重要技能。

网络技术联盟站 4698

YOLOv11改进策略【Neck】| BiFPN:双向特征金字塔网络-跨尺度连接和加权特征融合

可扩展的高效物体检测BiFPN(加权双向特征金字塔网络)

Limiiiing的博客 5498

Hibernate之多表查询

原生SQL多表查询 1.交叉连接(笛卡尔积) select * from A, B 2.内连接 (1)隐式内连接 select * from A, B where b.aid = a.id (2)显示内连接 select * from A inner join B on b.aid = a.id 3.外链接 (1)左外连接 select * from A left [outer

lilei0809的专栏 300

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Java 框架 01 — Hibernate 03(表关联及其配置文件设置、查询总结、HQL查询、Criteria查询)

文章目录0 回顾0.1 hibernate主键生成策略0.2 hibernate基本查询0.2.1 HQL0.2.2 Criteria0.2.3 SQL0.3 hibernate事务一、表关联的关系1.1 一对多(1-n)1.1.1 添加关联关系1.1.1.1 被引用表(1表)配置文件1.1.1.2 被应用表(n表)配置文件1.1.2 删除操作1.2 多对多(n-n)1.2.1 添加用户、角色/...

文泽路小男孩的博客 1085

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Hibernate框架学习day04(HQL_QBC查询详解、抓取策略优化机制)

1.1 上次课的内容回顾 Hibernate的一对多 表与表之间关系 一对多关系 多对多关系 一对一关系 Hibernate的一对多配置 搭建Hibernate基本环境 创建表 创建实体 一的一方 放的是多的一方的集合 多的一方 放的是一的一方的对象 创建映射 一的一方 配置的集合 多的一方 配置 编写测试类 Hibernate的一对多的操作 ...

weixin_42135811的博客 257

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

hibernate查询

用户的查询    *  单表的查询        *  页面上要显示的字段和数据库比,太少            select new Person(pid,pname) from Person;        *  页面上要显示的字段和数据库的字段差不多            from Person    *  多表的查询        客户和订单表         *  在一...

liguang159的博客 124

hibernate学习(三)

一.HQL语句使用HQL查询所有记录Session session = HibernateUtil.getOpensession(); Transaction transaction = session.beginTransaction(); String hql = "from com.lanou3g.User"; Query&lt;User&gt; query = session.create...

hehanHH的博客 315

Hibernate学习

表关系 多对多 一对多 一对一 一对多 建表原则: 在多的一方创建外键指向一的一方的主键 多对多 建表原则: 创建一个中间表,中间表中至少两个字段作为外键分别指向多对多双方的主键 一对一 建表原则有两种: 一种: 唯一外键对应: 假设一对一的任意一方为多,在多的一方创建外键指向一的一方的主键,然后将外键设置为唯一。 二种: 主键对应: 一方的主键作为另一方的主键。 一对多创建映射 (客户的映射) <!-- set 标签: * name属性: 多的一方的集合的属性名称 --> <set

kfcing的博客 277

Hibernate剩余部分整理

一、表关系转映射文件

zgfzmj的博客 136

Hibernate→HQL、query.list()返回数据类型、查询相关语句、分页、原生SQL、@注解、持久化对象状态及生命周期、一多关系、继承映射关系、逆向工程

HQL Query实例与表 session通用工具类 from 类→List<类>接收 映射类 仅查询商品 查询商品及所在商家 别名 返回数据类型定义 Iterator接收 未指定list返回数据类型,默认object[ ]对象数组List<object[ ]> 一个字段返回对象不是数组 new list返回数据类型List<List> new Map返回数据类型List<Map> Ma

实干、效率、武功、心法 376
上一篇: hibernate 实现多表连接查询(简单介绍)
下一篇: 设计模式--单例模式
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值