15.4. select
子句
select 子句选择将哪些对象与属性返 回到查询结果集中. 考虑如下情况:
select 子句选择将哪些对象与属性返 回到查询结果集中. 考虑如下情况:
代码内容
select mate from Cat as cat inner join cat.mate as mate |
该语句将选择mates of other Cats。(其他猫的配偶) 实际上, 你可以更简洁的用以下的查询语句表达相同的含义:
代码内容
select cat.mate from Cat cat |
查询语句可以返回值为任何类型的属性,包括返回类型为某种组件(Component)的属性:
代码内容
select cat.name from DomesticCat cat where cat.name like ’fri%’ select cust.name.firstName from Customer as cust |
查询语句可以返回多个对象和(或)属性,存放在 Object[]队列中,
代码内容
select mother, offspr, mate.name from DomesticCat as mother inner join mother.mate as mate left outer join mother.kittens as offspr |
或存放在一个List对象中,
代码内容
select new list(mother, offspr, mate.name) from DomesticCat as mother inner join mother.mate as mate left outer join mother.kittens as offspr |
也可能直接返回一个实际的类型安全的Java对象,
代码内容
select new Family(mother, mate, offspr) from DomesticCat as mother join mother.mate as mate left join mother.kittens as offspr |
假设类Family有一个合适的构造函数.
你可以使用关键字as给“被选择了的表达式”指派别名:
你可以使用关键字as给“被选择了的表达式”指派别名:
代码内容
select max(bodyWeight) as max, min(bodyWeight) as min, count(*) as n from Cat cat |
这种做法在与子句select new map一起使用时最有用:
代码内容
select new map( max(bodyWeight) as max, min(bodyWeight) as min, count(*) as n ) from Cat cat |
该查询返回了一个Map的对象,内容是别名与被选择的值组成的名-值映射。
15.5. 聚集函数
HQL查询甚至可以返回作用于属性之上的聚集函数的计算结果:
代码内容
select avg(cat.weight), sum(cat.weight), max(cat.weight), count(cat) from Cat cat |
受支持的聚集函数如下:
代码内容
avg(...), sum(...), min(...), max(...) count(*) count(...), count(distinct ...), count(all...) |
你可以在选择子句中使用数学操作符、连接以及经过验证的SQL函数:
select cat.weight + sum(kitten.weight)
代码内容
from Cat cat join cat.kittens kitten group by cat.id, cat.weight select firstName||’ ’||initial||’ ’||upper(lastName) from Person |
关键字distinct与all 也可以使用,它们具有与SQL相同的语义.
代码内容
select distinct cat.name from Cat cat select count(distinct cat.name), count(cat) from Cat cat |
15.6. 多态查询
一个如下的查询语句:
代码内容
from Cat as cat |
不仅返回Cat类的实例, 也同时返回子类 DomesticCat的实例. Hibernate 可以在from子句中指定任何 Java 类或接口. 查询会返回继承了该类的所有持久化子类 的实例或返回声明了该接口的所有持久化类的实例。下面的查询语句返回所有的被持久化的对象:
代码内容
from java.lang.Object o |
接口Named 可能被各种各样的持久化类声明:
代码内容
from Named n, Named m where n.name = m.name |
注意,最后的两个查询将需要超过一个的SQL SELECT.这表明order by子句 没有对整个结果集进行正确的排序. (这也说明你不能对这样的查询使用Query.scroll()方法.)
15.7. where 子句
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子句非常的强大,考虑如下情况:
null
该查询将被翻译成为一个含有表连接(内连接)的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 是一个属性,该属性被映射为<any>)。
代码内容
from AuditLog log, Payment payment where log.item.class = ’Payment’ and log.item.id = payment.id |
注意,在上面的查询与句中,log.item.class 和 payment.class 将涉及到完全不同的数据库中的列。