hibernate的查询——HQL

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的配置文件中添加true 1, false 0

则可以写这样的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语句放入配置文件中,而不是代码中。通过这种方式,可以大大提高程序的解耦。

例子(在映射文件中定义):

From Person as p where p.age > ?

该命名的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();

}


你可能感兴趣的:(Struts2)