from 是最简单的HQL语句,也是最基本的HQL语句。from 关键字后紧跟持久化类的类名。例如:

 from Person

  表明从Person持久化类中取出全部的实例。

  大部分时候,推荐位该Person的每个实例取一个别名。例如:

 from Person as p

  上面的as是可选的,但为了增加可读性,建议保留。

  from 后面还可以同时出现多个持久化类,此时将产生一个笛卡尔积或跨表连接,但实际上这种用法很少使用,因为通常我们可能需要使用跨表连接时,可以考虑使用隐士连接或者显示连接,而不是直接在from后紧跟多个表名。

  

  关联和连接

  当程序需要从多个数据表中取得数据时,SQL语句将会考虑使用多表连接查询。Hibernate使用关联映射来处理底层数据表之间的连接,一旦我们提供正确的映射后,当程序通过Hibernate进行持久化访问时,将可利用Hibernate的关联进行连接。

  HQL支持两种关联连接(join)形式: 隐式(implicit)与显式(explicit)。

  隐式连接形式不适用 join 关键字,使用英文点号(.)来隐式连接关联实体,而Hibernate底层将自动进行关联查询。例如如下HQL语句

 //查询Person持久化实体
from Person as p
where p.myEvents.titile > :title

  上面的p.myEvents属性的实质是一个持久化实体,因此Hibernate底层隐式自动进行连接查询。

  

  显式连接则需要使用 xxx join 关键字。例如下面的语句:

 from Person p
inner join p.myEvents event
where event.happenDate < :endDate

  使用显式连接 时可以为相关联的实体,甚至是关联集合中的全部元素指定一个别名。

  Hibernate支持的HQL连接直接借鉴了 SQL99 多表查询的关键字,可使用如下几种连接方法。

  》inner join (内连接),可简写成 join。

  》left outer join(左外连接),可简写成 left join。

  》right outer join(右外连接),可简写成right join。

  》full join(全连接),并不常用。

  使用显式连接时,还可通过HQL的with关键字来提供额外的连接条件,例如如下HQL语句:

 from Person p
inner join p.myEvents event
with p.id > event.id
where event.happenDate < :endDate

  Hibernate会将这种显式连接转换成SQL99多表连接的语法,所以HQL语句中with关键字的作用等同于SQL99中 on 关键字的作用;都是用于指定连接条件。通过在HQL语句中使用with关键字,可以让HQL语句执行非等值连接查询。

  

  不难发现 要想完全掌握HQL,不懂SQL是完全不行的。

  还有一点必须指出:由于此处的inner join, left join, right join, full join的实质依然是基于底层的SQL的内,左,外连接的,所以如果底层SQL不支持这些外连接,那么执行相应的HQL时就会相应的引发异常。

  对于隐式连接和显式连接还有如下两点区别:

  》隐式连接底层将转换为SQL99 的交叉连接,显式连接底层将转换成SQL99 的 inner join, left join, right join等连接。

  对于from Person p where p.myEvent.title > :title这条隐式连接的HQL语句,执行HQL查询后将看到产生如下所示的SQL语句。

 select
person0_.person_id as person1_0_,
person0_.name as name_0,
person0_.age as age0_,
person0_.event_id as event4_0_
from
person person0_ cross
join
event myevent1_
where
person0_.event_id = myevent1_.event_id
and myevent1_.title > ?

  而对于from Person p left join p.myEvents event where event.happenDate < :endDate 这条显式连接的HQL语句,执行HQL查询后将看到产生如下所示的SQL语句:

 select
person0_.person_id as person1_0_,
person0_.name as name0_,
person0_.age as age0_,
person0_.event_id as event4_0_
from person person0_
left outer join
event myevent1_
on person0_.event_id = myevent1_.event_id
where
myevent1_.happenDate < ?

  对比这两条SQL语句,不难发现第一条SQL语句是SQL99的交叉连接,而第二条SQL语句则是SQL99的左外连接语法——具体到底使用哪种连接方法,取决于HQL语句的显示连接使用了哪种连接方式。

  》隐式连接和显示连接查询后返回的结果不同。

  当HQL语句中省略select关键字时,使用隐式连接查询返回的结果是多个被查询实体组成的集合。如上面第一条SQL语句所示,它只选择person表中的数据列,所以查询得到的结果是Person对象组成的集合。

  当使用显式连接查询的HQL语句中省略select关键字时,返回的结果也是集合,但集合元素是被查询持久化对象,所有被关联的持久化对象所组成的数组。如上面的第二条SQL语句所示,他同时选择了person,event表中的所有数据列,查询得到的结果集的每条记录即包含了Person实体的全部属性,也包含了MyEvent实体的全部属性。Hibernate会把每条记录封装成一个集合元素,用属于Person的属性创建Person对象,属于MyEvent的属性创建MyEvent对象.....多个持久化实体最后封装成一个数组来作为集合元素。

  如:

         Session session = HibernateSessionFactory.getSession();
Transaction tx = session.beginTransaction();
String hql = "from Person p join p.myEvents event";
List<Object[]> datas = session.createQuery(hql).list();
for(Object[] data:datas){
System.out.println(data[0]);//输出Person持久化实体对象
System.out.println(data[1]);//输出MyEvent持久化实体对象
}
tx.commit();
session.close();

  关于隐式连接和显示连接还有非常主要的一点需要指出,这是由Hibernate版本升级所引发的问题。在Hibernate3.2.2之前的版本, Hibernate会对所有关联实体自动使用隐式连接。对于如下HQL语句:

 

 from Person p
where p.myEvents.title = :eventTitle

  无论如何, Hibernate将对上面的p.myEvents.title自动使用隐式连接,因此上面的HQL语句总是有效的。  

  从Hibernate3.2.3以后, Hibernate改变了这种隐式连接的策略,还是对于这条同样的HQL语句,则可能出现以后几种情况:

  》如果myEvents 是普通组件属性,或单个的关联实体,则Hibernate会自动生成隐式内连接,上面的HQL语句依然有效。

  》如果myEvents是一个集合(包括1-N,N-N关联),那么系统将出现:QueryException异常,异常提示信息为:

 org.hibernate.QueryException: illegal attempt to dereference collection

  根据Hibernate的官方说法:这样可以使的隐式连接更具确定性(原文:This makes implicit joins more deterministic)

  为此, Hibernate推荐上面的HQL语句写成:

 from Person p
inner join p.myEvents e
where e.title = :eventTitle

  这条HQL语句将会返回一个集合,集合元素是Person实体和MyEvent实体组成的数组。

  如果只想获取Person组成的集合,则需要改写成:

 select p
from Person p
join p.myEvents e
where e.title = :eventTitle

  但上面的语句可能返回多个完全相同的Person对象,想一想SQL多表连接查询的结果就可知道原因了。

  如果想得到由Person实体组成的集合,且元素不重复,应该改为如下SQL语句:

 select distinct p
from Person p
inner join p.myEvents e
where e.title = :eventTitle

  也就是说,对于Hibernate 3.2.3以后的版本,如果关联实体是单个实例或单个的组件属性,HQL依然可以可以使用英文句点(.)来隐式连接关联实体或组件;但如果关联实体是集合(包括1-N关联,N-N关联和集合元素是组件等),则必须使用 xxx join 来显式连接关联实体或组件。

  对于有集合属性的,Hibernate默认采用延迟加载策略。如果Session被关闭,Person实例将无法访问关联的scores属性。

  为了解决该问题,可以在Hibernate映射文件中指定 lazy = "false" 来关闭延迟加载。

  还有一种方法,使用join fetch,例如:

 from Person p
join fetch p.scores

  上面的关键字将导致Hibernate在初始化Person对象时,同时抓取该Person关联的scores集合属性。

  使用join fetch时通常无需指定别名,因为相关联的的对象不应在where字句(或其他任何字句)中使用。而且被关联的对象也不会再被查询的结果中直接返回,而是应该通过其父对象来访问。

  使用fetch关键字时有如下几个注意点

  》fetch不应该与setMaxResult()或setFirstResult()公用。因为这些操作都是基于结果集的,而在预先抓取集合类时可能包含重复的数据,即无法预先知道精确的行数。

  》fetch不能独立与with条件一起使用。

  》如果在一次查询中fetch多个集合,可以查询返回笛卡尔积,因此请多加注意。

  》对bag映射而言,同时join fetch多个集合可能出现非预期结果,因此需要谨慎使用。

  》full join fetch 与 right join fetch是没有任何意义的。

  如果在映射文件映射属性时同时指定 lazy =  "true" 启动了延迟加载(这种延迟加载是通过字节码增强来实现的),然后程序里有希望预加载那些原本应延迟加载的属性,则可以通过 fetch all properties 来强制Hibernate立即抓取这些属性。例如:

  

 from Document fetch all properties order by name
from Document doc fetch all properties where lower(doc.name) like '%cats%'

Hibernate的查询语言之HQL(二)——Hibernate查询的from字句的更多相关文章

  1. Hibernate的查询语言之HQL(一)——快速入门

    Hibernate提供异常强大的查询体系,使用Hibernat有多种查询方式可以选择:即可以使用Hibernate的HQL查询,也可以使用条件查询,甚至可以使用原生的SQL查询语句.不仅如此, Hib ...

  2. J2EE进阶(十七)Hibernate中常用的HQL查询方法(getHibernateTemplate())

    J2EE进阶(十七)Hibernate中常用的HQL查询方法(getHibernateTemplate())   当我们使用Hibernate进行数据的CRUD操作时,利用模版进行操作不失为一种方法. ...

  3. Hibernate hql(hibernate query language)基础查询

    在开发过程中,数据库的操作我们其实更多的用到的是查询功能,今天开始学习hql的查询. 1.加入必要的工具 2.Hibernate配备的一种非常强大的查询语言,这种查询语言看上去很像sql.但是不要被语 ...

  4. Hibernate查询语言(HQL)

    Hibernate查询语言(HQL)与SQL(结构化查询语言)相同,但不依赖于数据库表. 我们在HQL中使用类名,而不是表名. 所以是数据库独立的查询语言. HQL的优点 HQL有很多优点. 它们如下 ...

  5. hibernate学习系列-----(4)hibernate基本查询上篇:HQL基本查询

    紧接着上一篇,今天继续hibernate的学习总结,来聊一聊hibernate的基本查询方法,先说说HQL(hibernate Query Language):它是官方推荐的查询语言.在开始写代码之前 ...

  6. Java进阶知识13 Hibernate查询语言(HQL),本文以hibernate注解版为例讲解

    1.简单概述 1.1. 1) SQL:面向的是数据库 select * from tableName;2) HQL查询(Hibernate Query language): hibernate 提供的 ...

  7. java:Hibernate框架3(使用Myeclipse逆向工程生成实体和配置信息,hql语句各种查询(使用hibernate执行原生SQL语句,占位符和命名参数,封装Vo查询多个属性,聚合函数,链接查询,命名查询),Criteria)

    1.使用Myeclipse逆向工程生成实体和配置信息: 步骤1:配置MyEclipse Database Explorer: 步骤2:为项目添加hibernate的依赖: 此处打开后,点击next进入 ...

  8. Hibernate HQL多表查询

    1.内连接和迫切内连接 (1)内连接 HQL语句:from 实体类名 实体类别名 inner join 实体类别名.表示另一个表数据的集合名称 (2)迫切内连接 HQL语句:from 实体类名 实体类 ...

  9. Hibernate的HQL多表查询

    HQL的内连接查询 对于HQL内链接查询,查询的是两张表的数据,这两张表的数据首先是保存在数组之中,然后在将每一个数组保存在List集合之中进行返回 代码片段: @Test // 内连接 public ...

随机推荐

  1. Selenium firefox 版本问题

    问题:Unable to connect to host 127.0.0.1 on port 7055 after 45000 ms 原因: selenium-server-standalone-x. ...

  2. JavaScript之作用域与作用域链

    今天是2016的第一天,我们得扬帆起航踏上新的征程了.此篇阐述JavaScript中很重要的几个概念:作用域与作用域链及相关知识点. 我们先从变量与作用域的行为关系开始讨论. 变量作用域 JavaSc ...

  3. windows server作为文件服务器如何精细控制权限

    最近使用windows server 2003搭建了文件服务器,对于其中关于共享文件权限的精细控制有了较深的体会. 当前实现基本的共享文件目录结构是(上传图片真心费劲,大家将就一下吧): |--部门1 ...

  4. Java中sleep,wait,yield,join的区别

    sleep() wait() yield() join()用法与区别   1.sleep()方法 在指定时间内让当前正在执行的线程暂停执行,但不会释放“锁标志”.不推荐使用. sleep()使当前线程 ...

  5. Libgdx New 3D API 教程之 -- Libgdx中使用Materials

    This blog is a chinese version of xoppa's Libgdx new 3D api tutorial. For English version, please re ...

  6. java——递归调用

    递归函数调用调用本身,并通过自己的相应参数,这个计算过程中进行层,直到满足某些条件,只要停止呼叫. 递归函数的特点 1.函数要直接或间接调用自身. 2.要有递归终止条件检查.即递归终止的条件被满足后. ...

  7. React Native 从入门到原理

    React Native 是最近非常火的一个话题,介绍如何利用 React Native 进行开发的文章和书籍多如牛毛,但面向入门水平并介绍它工作原理的文章却寥寥无几. 本文分为两个部分:上半部分用通 ...

  8. Android系统移植与驱动开发--第四章

    第四章 源代码的下载和编译 一个android内核相当于4G,而一个Linux内个只有几百M,Linux内核相对于android内核来说实在是小巫见大巫.了解android源代码不一定要详细了解,只去 ...

  9. Linux access

    1.access函数 功能描述:检查调用进程是否可以对指定的文件执行某种操作. 用法: #include <unistd.h> #include <fcntl.h>int ac ...

  10. centos 安装nginx

    centos 安装nginx 安装依赖 更换源 yum install http://mirrors.163.com/centos/6.8/extras/x86_64/Packages/epel-re ...