⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hibernate2 参考文档之十.txt

📁 Hibernate使用说明书
💻 TXT
📖 第 1 页 / 共 2 页
字号:
Chapter 10. Hibernate查询语言(Query Language), 即HQL 
Prev     Next 

--------------------------------------------------------------------------------

Chapter 10. Hibernate查询语言(Query Language), 即HQL
Hibernate装备了一种极为有力的查询语言,(有意地)看上去很像SQL。但是别被语法蒙蔽,HQL是完全面向对象的,具备继承、多态和关联等特性。 

10.1. 大小写敏感性(Case Sensitivity)
除了Java类和属性名称外,查询都是大小写不敏感的。 所以, SeLeCT 和 sELEct 以及 SELECT 相同的,但是 net.sf.hibernate.eg.FOO 和 net.sf.hibernate.eg.Foo 是不同的, foo.barSet 和 foo.BARSET也是不同的。 

本手册使用小写的HQL关键词。有些用户认为在查询中使用大写的关键字更加易读,但是我们认为嵌入在Java代码中这样很难看。 

10.2. from 子句
可能最简单的Hibernate查询是这样的形式: 

from eg.Cat
它简单的返回所有eg.Cat类的实例。 

大部分情况下,你需要赋予它一个别名(alias),因为你在查询的其他地方也会引用这个Cat。 

from eg.Cat as cat
上面的语句为Cat赋予了一个别名cat 。所以后面的查询可以用这个简单的别名了。as关键字是可以省略的,我们也可以写成这样: 

from eg.Cat cat
可以出现多个类,结果是它们的笛卡尔积,或者称为“交叉”连接。 

from Formula, Parameter
from Formula as form, Parameter as param
让查询中的别名服从首字母小写的规则,我们认为这是一个好习惯。这和Java对局部变量的命名规范是一致的。(比如,domesticCat). 

10.3. 联合(Associations)和连接(joins)
你可以使用join定义两个实体的连接,同时指明别名。 

from eg.Cat as cat 
    inner join cat.mate as mate
    left outer join cat.kittens as kitten

from eg.Cat as cat left join cat.mate.kittens as kittens

from Formula form full join form.parameter param
支持的连接类型是从ANSI SQL借用的: 

内连接,inner join 

左外连接,left outer join 

右外连接,right outer join 

全连接,full join (不常使用) 

inner join, left outer join 和 right outer join 都可以简写。 

from eg.Cat as cat 
    join cat.mate as mate
    left join cat.kittens as kitten
并且,加上 "fetch"后缀的抓取连接可以让联合的对象随着它们的父对象的初始化而初始化,只需要一个select语句。这在初始化一个集合的时候特别有用。 

from eg.Cat as cat 
    inner join fetch cat.mate
    left join fetch cat.kittens
抓取连接一般不需要赋予别名,因为被联合的对象应该不会在where子句(或者任何其它子句)中出现。并且,被联合的对象也不会在查询结果中直接出现。它们是通过父对象进行访问的。 

请注意,目前的实现中,在一次查询中只会抓取一个集合(?原文为:only one collection role may be fetched in a query)。也请注意,在使用scroll()或者 iterate()方式调用的查询中,是禁止使用fetch构造的。最后,请注意full join fetch和right join fetch是没有意义的。 

10.4. select子句
select子句选择在结果集中返回哪些对象和属性。思考一下下面的例子: 

select mate 
from eg.Cat as cat 
    inner join cat.mate as mate
这个查询会选择出作为其它猫(Cat)朋友(mate)的那些猫。当然,你可以更加直接的写成下面的形式: 

select cat.mate from eg.Cat cat
你甚至可以选择集合元素,使用特殊的elements功能。下面的查询返回所有猫的小猫。 

select elements(cat.kittens) from eg.Cat cat
查询可以返回任何值类型的属性,包括组件类型的属性: 

select cat.name from eg.DomesticCat cat
where cat.name like 'fri%'

select cust.name.firstName from Customer as cust
查询可以用元素类型是Object[]的一个数组返回多个对象和/或多个属性。 

select mother, offspr, mate.name 
from eg.DomesticCat as mother
    inner join mother.mate as mate
    left outer join mother.kittens as offspr
或者实际上是类型安全的Java对象 

select new Family(mother, mate, offspr)
from eg.DomesticCat as mother
    join mother.mate as mate
    left join mother.kittens as offspr
上面的代码假定Family有一个合适的构造函数。 

10.5. 统计函数(Aggregate functions)
查询可以返回属性的统计函数。 

select avg(cat.weight), sum(cat.weight), max(cat.weight), count(cat)
from eg.Cat cat
在select子句中,统计函数的变量也可以是集合。 

select cat, count( elements(cat.kittens) ) 
from eg.Cat cat group by cat
下面是支持的统计函数列表: 

avg(...), sum(...), min(...), max(...) 

count(*) 

count(...), count(distinct ...), count(all...) 

distinct 和 all关键字的用法和语义与SQL相同。 

select distinct cat.name from eg.Cat cat

select count(distinct cat.name), count(cat) from eg.Cat cat
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会指向两个值,代表完全不同的数据库字段。 

10.8. 表达式(Expressions)
where子句允许出现的表达式包括了你在SQL中可以使用的大多数情况: 

数学操作+, -, *, / 

真假比较操作 =, >=, <=, <>, !=, like 

逻辑操作 and, or, not 

字符串连接 || 

SQL标量( scalar)函数,例如 upper() 和 lower() 

没有前缀的 ( )表示分组 

in, between, is null 

JDBC 传入参数? 

命名参数 :name, :start_date, :x1 

SQL 文字 'foo', 69, '1970-01-01 10:00:01.0' 

Java的public static final常量 比如 Color.TABBY 

in 和 between 可以如下例一样使用: 

from eg.DomesticCat cat where cat.name between 'A' and 'B'

from eg.DomesticCat cat where cat.name in ( 'Foo', 'Bar', 'Baz' )
其否定形式为 

from eg.DomesticCat cat where cat.name not between 'A' and 'B'

from eg.DomesticCat cat where cat.name not in ( 'Foo', 'Bar', 'Baz' )
类似的,is null和is not null可以用来测试null值。 

通过在Hibernate配置中声明HQL查询的替换方式,Boolean也是很容易在表达式中使用的: 

<property name="hibernate.query.substitutions">true 1, false 0</property>
在从HQL翻译成SQL的时候,关键字true和false就会被替换成1和0。 

from eg.Cat cat where cat.alive = true
你可以用特殊属性size来测试一个集合的长度,或者用特殊的size()函数也可以。 

from eg.Cat cat where cat.kittens.size > 0

from eg.Cat cat where size(cat.kittens) > 0
对于排序集合,你可以用minIndex和maxIndex来获取其最大索引值和最小索引值。类似的,minElement 和maxElement 可以用来获取集合中最小和最大的元素,前提是必须是基本类型的集合。 

from Calendar cal where cal.holidays.maxElement > current date
也有函数的形式(和上面的形式不同,函数形式是大小写不敏感的): 

from Order order where maxindex(order.items) > 100

from Order order where minelement(order.items) > 10000
SQL中的any, some, all, exists, in功能也是支持的,前提是必须把集合的元素或者索引集作为它们的参数(使用element和indices函数),或者使用子查询的结果作为参数。 

select mother from eg.Cat as mother, eg.Cat as kit
where kit in elements(foo.kittens)

select p from eg.NameList list, eg.Person p
where p.name = some elements(list.names)

from eg.Cat cat where exists elements(cat.kittens)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -