第6章 深入使用Hibernate 6.4 使用HQL查询

来源:互联网 发布:指纹识别算法 源代码 编辑:程序博客网 时间:2024/06/01 08:16

6.4 使用HQL查询

6.4.1 HQL查询

HQL查询依赖于Query类,每个Query实例对应一个查询对象。使用HQL查询按如下步骤进行:

(1)获取Hibernate session对象

(2)编写HQL语句

(3)以HQL语句作为参数,调用Session的createQuery方法创建查询对象

(4)如果HQL语句包含参数,则调用Query的setXxx方法为参数赋值

(5)调用Query对象的list()或uniqueResult()方法返回查询结果列表(持久化实体集)

//通过Session的createQuery方法创建Query对象List pl = sess.createQuery("select distinct p from Person p "+ "inner join p.myEvents event where event.happenDate "+ "between :firstDate and :endDate")//设置参数.setDate("firstDate",start).setDate("endDate",new Date())//返回结果集.list();
//以HQL语句创建Query对象.//执行setString方法为HQL语句的参数赋值//Query调用list方法访问查询的全部属性List pl = sess.createQuery("select distinct p.id,  p.name , p.age "+ "from Person p join "+ "p.myEvents").list();
//以HQL语句创建Query对象.//执行setString方法为HQL语句的参数赋值//Query调用list方法访问查询的全部实例List pl = sess.createQuery("select distinct p from Person p "+ "join p.myEvents where title = :eventTitle").setString("eventTitle","很普通的事情").list();
HQL的占位符即可使用英文问号(?),也可使用有名字的占位符,使用有名字占位符时,应该在占位符名字前增加英文冒号(:),如上HQL语句所示。

Query还包含如下两个方法:

setFirstResult(int firstResult):设置返回的结果集从第几条记录开始。

setMaxResults(int maxResults):设置本次查询返回的结果数目。

6.4.2 HQL查询的from字句

from Person as p 

表明从from持久化类中选出全部的实例。as 可选,推荐为每个实例区别名。

from后面还可同时出现多个持久化类,产生一个笛卡尔积的连接。也可以考虑使用隐式连接和显示连接。

6.4.3 关联和连接

HQL支持两种关联连接(join)形式:隐式(implicit)与显示(explicit)。

隐式连接形式不使用join关键字,使用英文点号(.)来隐式连接关联实体,而Hibernate底层将自动进行关联查询。

//查询Person持久化实体

from Person p where p.myEvent.title > :title

显示连接则需要使用xxx join 关键字

//使用显示连接

from Person p 

inner join p.myEvent event

where event.happenDate < :endDate

Hibernate可使用如下几种连接方式:

*inner join(内连接),可简写成join。

*left outer join(左外连接),可简化成left join。

*right outer join(右外连接),可简化成 right join。

*full join(全连接),并不使用。

使用显示连接时,还可使用HQL的with关键字来提供额外的连接条件,如下:

//使用显示连接

from Person p 

inner join p.myEvent event

with p.id > event.id

where event.happenDate < :endDate

对于隐式连接和显示连接还有如下两个特点:

*对于隐式连接底层将转换成SQL99的交叉连接,显示连接底层将转换成SQL99的inner join、left join、right join等连接。

*隐式连接和显示连接查询后返回的结果不同。

忽略select关键字时,返回结果集范围不一样。

6.4.4  HQL查询的select字句

select p.name from Person as p

select p.name.firstname from Person as p

在通常情况下,使用select字句查询的结果是集合,而集合元素就是select后的实例、属性等组成的数组。

select也支持将选择出的属性存入一个List对象,甚至直接封装成对象,如下:

select new ClassTest(p.name,p.address) from Person sa p

执行上面的HQL语句返回的结果是集合,但是集合元素是CLassTest对象。

6.4.5 HQL查询的聚集函数

 HQL支持的聚集函数与SQL的完全相同:avg、conut、max、min、sum等

select count(*) from Person

select max(p.age) from Person as p

select子句还支持字符串连接符、算术运算符,以及SQL函数。

selelct p.name || "" || p.address from Person as p

select子句也支持使用distinct和all关键字。

6.4.6 多态查询

HQL支持在from子句中指定任何java类和接口,查询会返回继承了该类的持久化子类的实例或返回实现该接口的持久化类的实例。

6.4.7 HQL 查询的where子句

where子句用于删选选中的结果,缩小选择的范围。

6.4.8 表达式

where 子句中允许使用大部分SQL支持的表达式,包括如下种类:

*数学运算符

*二进制比较运算符:=、>=、<=、<>、!=、like等

*逻辑运算符:and、or、not

*in、not in, between,is null , is not null,is empty,is not emty,member of and not member of等

*简单的case,case...when...then...else...end和case,case when...then...else...end等

*字符串连接符:如value1 || value2,或使用字符串连接函数concat(value1,value2).

*时间操作函数:current_date(),current_time(),current_timestamp(),second(),minute(),hour(),day(),month(),year()等

*HQL还支持EJB-QL 3.0所支持的函数或操作:substring(),trim(),lower(),upper(),length(),locate(),abs(),sqrt(),bit_length(),coalesce()和nullif()等

*支持底层数据库转换函数,如cast(... as ...),第二个参数是Hibernate的类型名,或者extract(... from ...),前提是底层数据库支持ANSI cast()和extract()。

*如果底层数据库支持如下单行函数:sign(),trunc(),rtrim(),sin(),则HQL语句也完全可以支持。

*HQL语句支持使用英文问号(?)作为参数占位符,这与JDBC的参数占位符一致;也使用命名参数占位符号,方法是在参数名前加英文冒号(:),例如:state_date,:x1等

除此之外,where子句还支持如下的特殊关键字用法:

*HQL index()函数,作用于join的有序集合的别名。

*HQL函数,把集合作为参数:size(),minelement(),maxelement(),minindex(),maxindex(),还有特别的elements()和indices函数,可以用数量词加以限定:some,all,exists,any,in.

*in和between...and可按如下方法使用:

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

from DomesticCat cat where cat.name in ('Foo','Bar','Baz');

*子句is null和is not null可以被用来测试空值

*size关键字用于返回一个集合的大小

*对于有序集合,还可使用minindex与maxindex函数代表最小与最大的索引序数。同理,可以使用minelement与maxelement函数代表集合中最小与最大的元素。

*还有特别有用的elements和indices()函数,用于返回指定集合的所有元素和所有索引。还可以使用SQL函数any,some,all,exists,in操作集合里的元素。

*在where子句中,有序集合的元素可以通过[]运算符访问。

6.4.9 order by 子句

6.4.10 group by子句

返回聚集值的查询可以对持久化类或组件属性的属性进行分组,分组使用group by字句。类似于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

6.4.11 子查询

HQL子查询只可以在select子句或者where子句中出现。

from Cat as cat

where not(cat.name,cat.color) in

(select cat.name,cat.color from DomesticCat cat);

select cat.id,(select max(kit.weight) from cat.kitten kit)

from Cat as cat

6.4.12 命名查询

HQL查询还支持将查询所用的HQL语句放入配置文件中,而不是代码中。

在Hibernate配置文件的<hibernate-mapping.../>元素中使用<query.../>子元素来定义命名查询,使用<query.../>元素只需指定一个name属性,指定该命名查询的名字。

<query name="myNamedQuery">
from Person as p where p.age > ?
</query>

Session里提供了getNamedQuery(String name)方法,该方法用于创建一个Query对象,一旦获得了Query对象,剩下的操作与普通HQL查询完全一样。

private void findByNamedQuery()throws Exception{//打开Hibernate的Session和事务Session sess = HibernateUtil.currentSession();Transaction tx = sess.beginTransaction();System.out.println("===执行命名查询===");//执行命名查询List pl = sess.getNamedQuery("myNamedQuery")//根据HQL语句里参数索引为参数赋值.setInteger(0 , 20).list();//迭代输出查询得到的每个Person对象for (Iterator pit = pl.iterator() ; pit.hasNext(); ){Person p = ( Person )pit.next();System.out.println(p.getName());}//提交事务、关闭Sessiontx.commit();HibernateUtil.closeSession();}

0 0
原创粉丝点击