您的位置:首页 > 其它

6.4.3:HQL的关联和连接

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

HQL支持两种关联连接形式: 隐式与显式。

隐式连接:

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

from Person p where p.myEvent.title>:title
上面的p.myEvent属性的实质是一个持久化实体,因此Hibernate底层隐式地自动进行连接查询。

显式连接:

显式连接则需要使用xxx join关键字,例如以下HQL语句:

from Person p
inner join p.myEvent event
where event.happenDate<:endDate
使用显式连接时可以为相关联的实体,甚至是关联集合中的全部元素指定一个别名。

Hibernate支持的HQL连接类型直接借鉴了SQL99多表查询的关键字,可用如下几种连接方式:

HQL的连接类型

inner join内连接,可简写为join
left outer join左外连接,可简写为left join
right outer join右外连接,可简写为right join
full join全连接,并不常用
使用显式连接时,还可通过HQL的关键字with来提供额外的连接条件,例如:

from Person p
inner join p.myEvent event
with p.id>event.id
where event.happenDate<:endDate
Hibernate会将这种显式连接转换成SQL99多表连接的语法,所以HQL语句中的with关键字的作用基本等同于SQL99中的on关键字的作用:都用于指定连接条件。通过在HQL语句中使用with关键字,可以让HQL语句执行非等值连接查询。

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

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

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

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

当HQL语句中省略select关键字时,使用隐式连接查询返回的结果是多个被查询实体组成的集合。当使用显式连接查询的HQL语句中省略select关键字时,返回的结果也是集合,但集合元素是被查询持久化对象、所有被关联的持久化对象所组成的数组。

关于隐式连接和显式连接还有非常重要的一点需要指出,这是由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异常,异常提示信息为:illegal attempt to dereference collection。

根据Hibernate的官方说法,这样可以使得隐式连接更具确定性。

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

from Person p
inner join p.myEvents e
where e.title=:eventTitle
这条HQL语句将会返回一个集合,集合元素是Person实体和MyEvent实体组成的数组。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: