您的位置:首页 > 其它

Hibernate学习之---使用HQL查询

2017-08-07 12:14 197 查看

1.HQL查询

HQL是一种面向对象的查询。SQL的操作对象是数据表、列等数据库对象,而HQL的操作对象是类、实例、属性等。

HQL是完全面向对象的查询语句,因此可以支持继承、多态等特性。

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

获取Hibernate Session对象。

编写HQL语句。

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

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

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

HQL的占位符既可使用英文问号+索引的形式(?N);也可使用有名字的占位符,使用有名字的占位符时,应该在占位符名字前增加英文冒号(:)。

Query还包含两个方法:

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

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

HQL语句本身不区分大小写的。但是HQL语句中所使用的包名、类名、实例名、属性名都区分大小写。

2.HQL查询的from子句

form关键字后紧跟持久化类的类型。

大部分时间推荐为Person的每个实例起别名。

from Person as p


p的命名规则是第一个单词的首字母小写,后面每个单词的首字母大写。

as关键字是可选。

3.关联和连接

当程序需要从多个数据表中取得数据时,SQL语句将会考虑使用多表连接查询。Hibernate使用关联映射来处理底层数据表之间的连接,一旦提供了正确的关联映射后,当程序通过Hibernate进行持久化访问时,将可利用Hibernate的关联来进行连接。

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

隐式连接形式不使用join关键字,使用英文点号(.)来隐式连接关联实体。

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


p.myEvent属性的实质是一个持久化实体。

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

from Person p inner join p.myEvent event where event.happenDate < :endDate


使用显示连接时可以为相关联的实体,甚至是关联集合中
bf33
的全部属性指定一个别名。

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等连接。

当HQL语句中省略select关键字时,使用隐式连接查询返回的结果是多个被查询实体组成的集合,使用显示连接查询返回的结果也是集合,但集合元素是被查询的持久化对象、所有被关联的持久化对象所组成的数组。

如果关联实体是单个实体或单个的组件属性,HQL依然可以使用英文点号(.)来隐式连接关联实体或组件;但如果关联实体是集合(包括1-N关联、N-N关联和和元素是组件等),则必须使用xxx join来显示连接关联实体或组件。

对于有集合属性的,Hibernate默认采用延迟加载策略。例如:对于持久化类Person,有集合属性scores。加载Person实例时,默认不加载scores属性。如果session被关闭,Person实例将无法访问关联的scores属性。

Hibernate持久化注解中指定fetch=FetchType.EAGER来关闭延迟加载。

from Person as p
join fetch p.scores


fetch 关键字将导致Hibernate在初始化Person对象时,同时抓取该Person关联的scores集合属性(或关联实体)。

使用join fetch 时通常无须指定别名,因为相关联的对象不应当在where子句(或其他任何子句)中使用。而且被关联的对象也不会再被查询的结果中直接返回,而是应该通过其父对象来访问。

fetch不应该与setMaxResults()或setFirstResult()共用。因为这些操作是基于结果集的,而在预先抓取集合类时可能包含重复的数据,即无法预先知道精确的行数。

fetch不能与独立的with条件一起使用。

如果在一次查询中fetch多个集合,可以查询返回笛卡儿积。

full join fetch 与right join fetch 是没有任何意义的。

程序希望预加载原本应延迟加载的属性,则可以通过fetch all properties来强制Hibernate立即抓取这些属性。

4.HQL查询的select子句

select子句用于选择指定的属性或直接选择某个实体,当然select选择的属性必须是from后持久化类包含的属性。

select p.name from Person as p
//选择组件属性包含的属性
select p.name.firstName from Person as p


使用select子句查询的结果是集合,而集合元素就是select后的实例、属性等组成的数组。

select 也支持将选择出的属性存入一个List对象中

//其集合元素是List对象(默认的集合元素是数组)
select new list(p.name,p.address) from Person as p


甚至可以将选择出的属性值直接封装成对象

//前提是ClassTest支持p.name,p.address的构造器
select new ClassTest(p.name,p.address) from Person as p


select new map(p.name as personName) from Person as p


执行上面的HQL语句返回的结果是集合,其中集合元素时Map对象,以personName作为Map的key,实际选出的值作为Map的value。

5.HQL查询的聚集函数

avg:计算属性平均值。

count:统计选择对象的数量。

max:统计属性值的最大值。

min:统计属性值的最小值。

sum:计算属性值的总和。

select max(p.age) from Person as p


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

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


select子句也支持使用distinct和all关键字,此时效果与SQL中的效果相同。

6.多态查询

HQL语句被设计成能理解多态查询,from后跟持久化类名,不仅会查询出该持久化类的全部实例,还会查询出该类的子类的全部实例。(前提是两个持久化类完成正确的继承映射)。

from java.lang.Object o


7.HQL查询的where子句

where子句用于筛选选中的结果,缩小选择的范围。如果没有为持久化实例命名别名,则可以直接使用属性名来引用属性。

from Person where name like 'tom%'


8.表达式

where子句中允许使用大部分SQL支持的表达式。

9.order by子句

查询返回的集合可以根据类或组件属性的任何属性进行排序。

from Person p
order by p.name,p.age


还可使用asc或desc关键字指定升序或降序的排序规则。

from Person p
order by p.name asc,p.age desc


10.group by子句

返回聚集值的查询可以对持久化类或组件属性的属性进行分组,分组使用group by子句。

select cat.color,sum(cat.weight),count(cat)
from Cat cat
gruop by cat.color


having子句用于对分组进行过滤。

select cat.color,sum(cat.weight),count(cat)
from Cat cat
gruop by cat.color
having cat.color in (eg.Color.TABBY,eg.Color.BLACK)


gruop by 子句与order by子句中都不能包含算术表达式。

11.子查询

HQL中的子查询需要使用英文括号()括起来

from Cat as fatcat
where fatcat.weight > (select avg(cat.weight) from DomesticCat cat)


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

12.命名查询

@NamedQuery注解来配置命名查询。

如果使用多个@NamedQuery定于命名查询,则可使用@NamedQueries来组合多个@NamedQuery。

@Entity
@Table(name="person")
@NamedQuery(name="myNamedQuery",query="from Person p where p.age > ?")
public class Person{

}


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

main{
List p1 = sess.getNamedQuery("myNamedQuery").setInteger(0,20).list();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: