Hibernate配备了一种非常强大的Hibernate查询语言,这种语言看上去很像SQL。本文主要介绍where子句、order by子句、group by子句。但是不要被语法结构 上的相似所迷惑,HQL是非常有意识的被设计为完全面向对象的查询,它可以理解如继承、多态 和关联之类的概念。
1. where子句
Hibernate查询语言where子句允许你将返回的实例列表的范围缩小. 如果没有指定别名,你可以使用属性名来直接引用属性:
- from Cat where name='Fritz'
如果指派了别名,需要使用完整的属性名:
- from Cat as cat where cat.name='Fritz'
返回名为(属性name等于)'Fritz'的Cat类的实例。
- select foo
- from Foo foo, Bar bar
- where foo.startDate = bar.date
将返回所有满足下面条件的Foo类的实例: 存在如下的bar的一个实例,其date属性等于 Foo的startDate属性。 复合路径表达式使得where子句非常的强大,考虑如下情况:
- from Cat cat where cat.mate.name is not null
该Hibernate查询将被翻译成为一个含有表连接(内连接)的SQL查询。如果你打算写像这样的查询语句
- from Foo foo
- where foo.bar.baz.customer.address.city is not null
在SQL中,你为达此目的将需要进行一个四表连接的查询。
=运算符不仅可以被用来比较属性的值,也可以用来比较实例:
- from Cat cat, Cat rival where cat.mate = rival.mate
- select cat, mate
- from Cat cat, Cat mate
- where cat.mate = mate
特殊属性(小写)id可以用来表示一个对象的唯一的标识符。(你也可以使用该对象的属性名。)
- from Cat as cat where cat.id = 123
- from 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在进行多态持久化的情况下被用来存取一个实例的鉴别值(discriminator value)。 一个嵌入到where子句中的Java类的名字将被转换为该类的鉴别值。
- from Cat cat where cat.class = DomesticCat
你也可以声明一个属性的类型是组件或者复合用户类型(以及由组件构成的组件等等)。永远不要尝试使用以组件类型来结尾的路径表达式(path-expression) (与此相反,你应当使用组件的一个属性来结尾)。 举例来说,如果store.owner含有一个包含了组件的实体address
- store.owner.address.city // 正确
- store.owner.address // 错误!
一个“任意”类型有两个特殊的属性id和class, 来允许我们按照下面的方式表达一个连接(AuditLog.item 是一个属性,该属性被映射为
- from AuditLog log, Payment payment
- where log.item.class = 'Payment' and log.item.id = payment.id
注意,在上面的查询与句中,log.item.class 和 payment.class 将涉及到完全不同的数据库中的列。
2. order by子句
查询返回的列表(list)可以按照一个返回的类或组件(components)中的任何属性(property)进行排序:
- from DomesticCat cat
- order by cat.name asc, cat.weight desc, cat.birthdate
可选的asc或desc关键字指明了按照升序或降序进行排序.
- select cat.color, sum(cat.weight), count(cat)
- from Cat cat
- group by cat.color
- select foo.id, avg(name), max(name)
- from Foo foo join foo.names name
- group by foo.id
3. group by子句
一个返回聚集值(aggregate values)的查询可以按照一个返回的类或组件(components)中的任何属性(property)进行分组:
- select cat.color, sum(cat.weight), count(cat)
- from Cat cat
- group by cat.color
- having cat.color in (eg.Color.TABBY, eg.Color.BLACK)
having子句在这里也允许使用.
- select cat.color, sum(cat.weight), count(cat)
- from Cat cat
- group by cat.color
- having cat.color in (eg.Color.TABBY, eg.Color.BLACK)
如果底层的数据库支持的话(例如不能在MySQL中使用),SQL的一般函数与聚集函数也可以出现 在having与order by 子句中。
- select cat
- from Cat cat
- join cat.kittens kitten
- group by cat
- having avg(kitten.weight) > 100
- order by count(kitten) asc, sum(kitten.weight) desc
注意group by子句与 order by子句中都不能包含算术表达式(arithmetic expressions).
【编辑推荐】