HQL(hibernate query language的缩写),它与SQL语法很像,但是它是一个面向对象的查询语言。它的操作对象是类、实例、属性等。当然它也具有面向对象的特征(继承、多态等)。
其中有一个很重要的接口:Query
这个接口的方法设计采用方法链的方式,与jquery的设计方式一样的。例如它里面的setXxx方法返回值也是Query本身,并且它还包括两个方法:1、setFirstResult(int firstResult):设置返回的结果集从第几条记录开始;2、setMaxResult(int maxResult):设置本次查询返回的结果数。
语句分析:
1. from语句
格式:from [className] as [name]
作用:从某个类中挑选出全部实例
注意:类的别名也应该遵循java的命名规则:第一个单词的首字母小写,后面的每个单词的首字母大写。
例子:from Person as p 筛选Person类的所有实例。
2. select语句
格式:select [attr]|[collection] from [className] as [name]
作用:选择指定的属性(存储到指定的集合中)
此外:select还支持字符串连接符、算数运算符及SQL函数,它还支持distinct和all关键字。
例子:
a、 select p.name fromPerson as p
b、 select p.name.firstName from Person as p
c、 select new list(p.name,p.address) from Person as p 将查询内容存储到List的一个对象中。
d、 select new ClassTest(p.name,p.address) from Person as p ClassTest必须有一个以两个字符串为参数的构造函数。
e、 select p.name as personName from Person as p
f、 select new map(p.name as personName) from Person as p 这种情况下以personName为key,将实际选出的值作为value。
g、 select p.name || “ ” || p.assress from Person as p
3. 聚集函数
有五种聚集函数:
a、 avg:计算属性平均值
b、 count;统计选择对象的数量
c、 max:统计属性值的最大值
d、 min:统计属性值的最小值
e、 sum:计算属性值的总和。
例子:select count(*) from Person select max(p.age) from Person as p
4. 多态查询
理解:与java中的多态类似,当我们查询某一个接口的时候,就会自动查询该接口的所有实现类及其子类。
例子:from java.lang.Object o 会查询所有被持久化的对象(在hibernate.cfg.xml中配置过的内容)。
5. where语句
作用:它用于筛选选中的结果,以缩小选择的范围。如果没有为持久化实例另起别名,可以直接使用属性名引用属性。
例子:
a、 from Person where name like “tom%” <=> from Person as p where p.name like “tom%”
b、 from Cat cat where cat.mate.name like “kit%” 被翻译后的SQL语句为:select * from cat_table as cat_table1 as table2 where table1.mate = table2.id and table1.name like “kit%”
c、 from Foo foo where foo.bar.baz.customer.address.city like “jiyuan%” 它翻译成SQL查询语句后,将变成一个四表连接的查询,“=”运算符不仅可以用来属性比较,而且还可以进行实例比较:select cat,mate from Cat cat, Cat mate where cat.mate = mate
d、 from Cat as cat where cat.id = 123 注意:特殊属性(小写)id可以用来表示一个对象的标识符(也可以使用该对象的属性名),该类中可以不定义id这个变量,hibernate会自动将其识别为该类的主键。
e、 from Person as person where person.id.country = ‘AU’ and person.id.medicareNumber = 123456
from Account as account where account.owner.id.country = ‘AU’ and account.owner.id.medicareNumber = 123456
注意:当特殊属性为引用类型(复合主键,例如:成绩表的sno和cno为主键)时,也可以用id作为标识符。
f、 from Cat cat where cat.class = DomesticCat
g、 where子句中的属性表达式必须以基本类型或者java.lang.String结尾
6. 表达式
a、 数学运算符:+=*/等
b、 二进制比较运算符:=、>=、<=、<>、!=、like等
c、 逻辑运算符and、or、not等
d、 in, not in, between, is null, is not null, is empty, is not empty, member of and not member of 等
e、 简单的case, case … when … then … else … end 和 case, case when … then … else … end等。
f、 字符串连接符 value1 || value2 或者使用字符串连接函数concat(value1, value2)。
g、 时间操作函数:current_date(), current_time(), current_timestamp(), second(), minute(), hour(), day(), month(), yeay()等。
h、 HQL还支持EJB-QL3.0所有的函数或操作:subString(), trim(), lower(), upper(), length(), locate(), abs(), sqrt(), bit_length(), coalesce() 和 nullif() 等。
i、 还支持数据库的类型转换函数,如cast(… as …),第二个参数是hibernate的类型名,或者extract(… from …),前提是底层数据库支持ANSI cast() 和 extract()。
j、 如果底层数据库支持单行函数:sign(), trunk(), rtrim(), sin()。则HQL语句也完全可以支持。
k、 HQL语句支持用“?”作为参数占位符,这与JDBC的参数占位符一样,也可以使用命名参数站位符号,方法是在参数名前面增加冒号“:”,如::start_date, :x1 等。
l、 也可以字where子句中使用SQL常量,如’foo’,69,’1970-01-04 10:00:01.0’等
m、 还可以再HQL语句中使用java public static final 类型的常量,如:eg.Color.TABBY。
n、 in与between … and 可以这样使用:
from DomesticCat cat where cat.name between ‘A’ and ‘B’
from DomesticCat cat where cat.name in (‘foo’, ‘bar’, ‘baz’)
o、 也支持not in 和 not between … and:
from DomesticCat cat where cat.name not between ‘A’ and ‘B’
from DomesticCat cat where cat.name not in (‘foo’, ‘bar’, ‘baz’)
p、 子句is null 与 is not null可以被用来测试空值
from DomesticCat cat where cat.name is null;
from Person as p where p.address is not null;
如果在hibernate的配置文件中添加<property name=”hibernate.query.substitutions”>true 1, false 0</property>
则可以写这样的HQL:from Cat cat where cat.alive = true
q、 Size关键字用于返回一个集合的大小,例如:
from Cat cat where cat.kittens.size > 0;
from Cat cat where size(cat.kittens) > 0;
r、 对于有序集合,还可以使用minindex 与 maxindex 函数代表最小与最大的索引序数。同理,可以使用minelement 与 maxelement 函数代表集合中最小与最大的元素。例如:
from Calendar cal where maxelement(cal.holidays) > current date;
from Order order where maxindex(order.items) > 100;
from Order order where minelement(order.items) > 1000;
s、 可以使用SQL函数如:any, some, all, exists, in等来操作集合里的元素,例如:
//操作集合元素
select mother from Cat as mother ,Cat as kit where kit in elements(foo.kittens)
//p的name属性等于集合中某个元素的name属性
select p from NameList list, Person p where p.name = some elements(list.names)
//操作集合元素
from Cat cat where exists elements(cat.kittens)
from Player p where 3 > all elements(p.scores)
from Show show where ‘fizard’ in indices(show.acts)
注意:在这些结构变量中:size, elements, indices, minindex, maxindex, maxindex, minelement, maxelement等,只能在where子句中使用
t、 在where子句中,有序集合的元素(arrays, lists, maps)可以通过[]运算符访问。
//items是有序集合属性,items[0]代表第一个元素
from Order order where order.items[0].id = 1234
//holidays 是map集合属性,holidays[national day]是代表其中一个元素
select person from Person person, Calendar calendar where calendar.holiday[‘national day’] = person.birthday and person.nationality.calendar = calendar
//下面同时使用list集合和map集合属性
select item from Item item, Order order where order.items[order.deliveredItemIndices[0]] = item and order.id = 11
select item from Item item, Order order where order.items[maxindex(order.items)] = item and order.id = 11
在【】中的表达式也可以为一个算数表达式,例如:
Select item from Item item, Order order where order.item[size(order.items) - 1] = item
例子:
select cust
from Product prod, Store store inner join store.customers cust
where prod.name = ‘widget’
and store.location.name in (‘Melbourne’, ‘Sydeny’)
and prod = all elements (cust.currentOrder.lineItems)
7. order by子句
查询返回的列表(list),可以根据类或引用属性的任何属性来进行排序,例如:
from Person as p order by p.name, p.age
还可以使用asc和desc关键字指定升序或者降序的排列规则,例如:
from Person as p
order by p.name asc, p.age desc
如果没有指定排序规则时,默认采用升序规则,与是否使用asc关键字没有区别,加上asc是升序,不加asc也是升序。
8. group by子句
利用返回聚集值的查询,可以对持久化类或引用属性的属性进行分组,分组时可使用group by语句,看下面的HQL语句:
select cat.color, sum(cat.weight), count(cat)
from Cat cat
group by cat,color
类似于SQL的规则,出现在select后的属性要么出现在聚集函数中,要么出现在group by的属性列表中。看下面的示例:
//select 后出现的id处出现在group by之后,而name属性则出现在聚集函数中
select foo.id, avg(name), max(name)
from Foo foo join foo.names name
group by foo.id
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)
注意:having子句用于对分组进行过滤,因此having子句只能在有group by子句时才可以使用,没有group by子句,则不能使用having子句。
group by子句与order by子句中都不能包含算数表达式。
9. 子查询
如果底层数据库支持子查询,则可以在HQL语句中使用子查询。与SQL中子查询相似的是,HQL中的子查询也需要用”()”括起来。例如:
from Cat as fatcat
where fatcat.weight > (select avg(cat.weight) from DomesticCat cat)
如果select包含多个属性,则应该使用元祖构造符:
from Cat as cat
where not (cat.name, cat.color) in
(
select cat.name, cat.color from DomesticCat cat
)
10. fetch关键字
对于集合属性,hibernate默认采用延迟加载策略。例如,对于持久化类Person,有集合属性scores。加载Person实例时,默认不加载scores属性。如果Session被关闭,则Person实例将无法访问关联的scores属性。
那么我们可以取消延迟加载策略,或者使用fetch join。例如:
from Person as p join p.scores 它将会初始化Person的scores集合属性。
如果使用了属性级别的延迟加载,则可以用fetch all properties来强制hibernate立即抓取那些原本需要延迟加载的属性。例如:
from Document fetch all properties order by name
from Document doc fetch all properties where lower(doc.name) like ‘%cats%’
11. 命名查询
HQL查询还支持将查询所用的HQL语句放入配置文件中,而不是代码中。通过这种方式,可以大大提高程序的解耦。
例子(在映射文件中定义):
<!—定义命名查询 -->
<query name=”myNamedQuery”>
<!—此处确定命名查询的HQL语句 -->
From Person as p where p.age > ?
</query>
该命名的HQL查询可以直接通过Session访问,调用命名查询的示例代码如下:
Private void findByName() throws Exception
{
//获得Hibernate Session对象
Session session = HibernateUtil.currentSession();
//开始事务
Transaction tx = session.beginTransaction();
System.out.println(“执行命名查询”);
List list = session.getNameQuery(“myNamedQuery”)
//为参数传值,Query setInteger(int position, int val)
.setInteger(0,20)
.list();
//遍历集合结果集
for(Iterator it = p1.iterator(); it.haxNext();)
{
Person p = (Person) it.next();
System.out.println(p.getName());
}
//提交事务
tx.commit();
HibernateUtil.closeSession();
}