ITEEDU

10.6. 多态(polymorphism)

类似下面的查询:

from eg.Cat as cat

返回的实例不仅仅是Cat,也有可能是子类的实例,比如DomesticCat。Hibernate查询可以在from子句中使用任何Java类或者接口的名字。查询可能返回所有继承自这个类或者实现这个接口的持久化类的实例。下列查询会返回所有的持久化对象:

from java.lang.Object o

可能有多个持久化类都实现了Named接口:

from eg.Named n, eg.Named m where n.name = m.name

请注意,上面两个查询都使用了超过一个SQL的SELECT。这意味着order by子句将不会正确排序。(这也意味着你不能对这些查询使用Query.scroll()。)

10.7. where子句

where子句让你缩小你要返回的实例的列表范围。

from eg.Cat as cat where cat.name='Fritz'

返回所有名字为'Fritz'的Cat的实例。

select foo 
from eg.Foo foo, eg.Bar bar
where foo.startDate = bar.date

会返回所有的满足下列条件的Foo实例,它们存在一个对应的bar实例,其date属性与Foo的startDate属性相等。复合路径表达式令where子句变得极为有力。思考下面的例子:

from eg.Cat cat where cat.mate.name is not null

这个查询会被翻译为带有一个表间(inner)join的SQL查询。如果你写下类似这样的语句:

from eg.Foo foo  
where foo.bar.baz.customer.address.city is not null

你最终会得到的查询,其对应的SQL需要4个表间连接。

=操作符不仅仅用于判断属性是否相等,也可以用于实例:

from eg.Cat cat, eg.Cat rival where cat.mate = rival.mate

select cat, mate 
from eg.Cat cat, eg.Cat mate
where cat.mate = mate

特别的,小写的id可以用来表示一个对象的惟一标识。(你可以使用它的属性名。)

from eg.Cat as cat where cat.id = 123

from eg.Cat as cat where cat.mate.id = 69

第二个查询是很高效的。不需要进行表间连接!

组合的标示符也可以使用。假设Person有一个组合标示符,是由country和medicareNumber组合而成的。

from bank.Person person
where person.id.country = 'AU' 
    and person.id.medicareNumber = 123456

from bank.Account account
where account.owner.id.country = 'AU' 
    and account.owner.id.medicareNumber = 123456

又一次,第二个查询不需要表间连接。

类似的,在存在多态持久化的情况下,特殊属性class用于获取某个实例的辨识值。在where子句中嵌入的Java类名将会转换为它的辨识值。

from eg.Cat cat where cat.class = eg.DomesticCat

你也可以指定组件(或者是组件的组件,依次类推)或者组合类型中的属性。但是在一个存在路径的表达式中,最后不能以一个组件类型的属性结尾。(这里不是指组件的属性)。比如,假若store.owner这个实体的的address是一个组件

store.owner.address.city    //okay
store.owner.address         //error!

“任意(any)”类型也有特殊的id属性和class属性,这可以让我们用下面的形式来表达连接(这里AuditLog.item是一个对应到<ant>的属性)。

from eg.AuditLog log, eg.Payment payment 
where log.item.class = 'eg.Payment' and log.item.id = payment.id

注意上面查询中,log.item.class和payment.class会指向两个值,代表完全不同的数据库字段。