HQL检索方式
QBC检索方式
本地SQL检索方式
Hibernate提供的检索对象的方式
导航对象图检索方式
根据已经加载的对象,导航到其他对象。例如,对于已经加载的Customer对象,调用它的getOrders().iterator()方法就可以导航到所有关联的Order对象,假如在关联级别使用了延迟加载检索策略,那么首次执行此方法时,Hibernate会从数据库中加载关联的Order对象,否则就从缓存中取得Order对象。
OID检索方式
按照对象的OID来检索对象。Session的get()和load()方法提供了这种功能。如果在应用程序中事先知道了OID,就可以使用这种检索对象的方式。
HQL检索方式
使用面向对象的HQL查询语言。Session的find()方法用于执行HQL查询语句。此外,Hibernate还提供了Query接口,它是Hibernate提供的专门的HQL查询接口,能够执行各种复杂的HQL查询语句。本章有时把HQL检索方式简称为HQL。
QBC检索方式
使用QBC(Query By Criteria)API来检索对象。这种API封装了基于字符串形式的查询语句,提供了更加面向对象的接口。本章有时把QBC检索方式简称为QBC。
本地SQL检索方式
使用本地数据库的SQL查询语句。Hibernate会负责把检索到的JDBC ResultSet结果集映射为持久化对象图。
HQL检索方式
HQL(Hibernate Query Language)是面向对象的查询语言,它和SQL查询语言有些相似。在Hibernate提供的各种检索方式中,HQL是使用最广的一种检索方式。它具有以下功能:
在查询语句中设定各种查询条件
支持投影查询,即仅检索出对象的部分属性
支持分页查询
支持连接查询
支持分组查询,允许使用having和group by关键字
提供内置聚集函数,如sum()、min()和max()
能够调用用户定义的SQL函数
支持子查询,即嵌入式查询
支持动态绑定参数
Session的find()方法以及Query接口
Session类的find()方法以及Query接口都支持HQL检索方式。
这两者的区别在于,前者只是执行一些简单HQL查询语句的便捷方法,它不具有动态绑定参数的功能,而且在Hibernate3.x版本中,已经淘汰了find()方法;而Query接口才是真正的HQL查询接口,它提供了以上列出的各种查询功能。
HQL检索步骤
//创建一个Query对象
Query query=session.createQuery("from Customer as c where "
+" c.name=:customerName "
+"and c.age=:customerAge");
//动态绑定参数
query.setString("customerName","Tom");
query.setInteger("customerAge",21);
//执行查询语句,返回查询结果
List result= query.list();
HQL检索步骤
(1)通过Session的createQuery()方法创建一个Query对象,它包含一个HQL查询语句。HQL查询语句可以包含命名参数,如“customerName”和“customerAge”都是命名参数。
(2)动态绑定参数。Query接口提供了给各种类型的命名参数赋值的方法,例如setString()方法用于为字符串类型的customerName命名参数赋值。
(3)调用Query的list()方法执行查询语句。该方法返回List类型的查询结果,在List集合中存放了符合查询条件的持久化对象。
方法链编程风格
List result=session.createQuery("……")
.setString("customerName","Tom")
.setInteger("customerAge",21)
.list();
方法链编程风格能使程序代码更加简洁。
QBC检索方式
采用HQL检索方式时,在应用程序中需要定义基于字符串形式的HQL查询语句。
QBC API 提供了检索对象的另一种方式,它主要由Criteria接口、Criterion接口和Expression类组成,它支持在运行时动态生成查询语句。
QBC检索方式
//创建一个Criteria对象
Criteria criteria=session.createCriteria(Customer.class);
//设定查询条件,然后把查询条件加入到Criteria中
Criterion criterion1= Expression.like("name", "T%") ;
Criterion criterion2= Expression.eq("age", new Integer(21)) ;
criteria=criteria.add(criterion1);
criteria=criteria.add(criterion2);
//执行查询语句,返回查询结果
List result=criteria.list();
QBC检索步骤
(1)调用Session的createCriteria()方法创建一个Criteria对象。
(2)设定查询条件。Expression类提供了一系列用于设定查询条件的静态方法,这些静态方法都返回Criterion实例,每个Criterion实例代表一个查询条件。Criteria的add()方法用于加入查询条件。
(3)调用Criteria的list()方法执行查询语句。该方法返回List类型的查询结果,在List集合中存放了符合查询条件的持久化对象。对于以上程序代码,当运行Criteria的list()方法时,Hibernate执行的SQL查询语句为:
select * from CUSTOMERS where NAME like 'T%' and AGE=21;
方法链编程风格
List result=session.createCriteria(Customer.class)
.add(Expression.like("name", "T%")
.add(Expression.eq("age", newInteger(21))
.list();
比较运算(大于)
List list = session.createQuery("from Hx c where c.id>0")
.list();
List list = session.createCriteria(Hx.class)
.add(Expression.gt("id", new Integer(0)))
.list();
比较运算(不等于)
List list = session.createQuery("from Hx c where c.id<>0")
.list();
List list = session.createCriteria(Hx.class)
.add(Expression.not(Expression.eq("name", "zmx")))
.list();
比较运算(不等)
List list = session.createQuery("from Hx c where c.name is null")
.list();
List list = session.createCriteria(Hx.class)
.add(Expression.not(Expression.isNull("name")))
.list();
比较运算(范围)
List list = session.createQuery("from Hx c where c.name in(‘zmx’)")
.list();
String names[]={“zmx”,”hx”};
List list = session.createCriteria(Hx.class)
.add(Expression.in(“name”,names))
.list();
模糊查询
List list = session.createQuery("from Hx c where c.name like ‘Z%’")
.list();
List list = session.createCriteria(Hx.class)
.add(Expression.like(“name”,”Z%”)))
.list();
QBE查询(query by Example)
它是QBC的子功能,允许创建一个对象模板,然后检索出所有和模板相同的对象,但功能不是很强大,且只支持=和like运算符
Hx hx = new Hx();
hx.setAge(33);
List list = session.createCriteria(Hx.class)
.add(Example.create(hx)).list();
查询排序
HQL方式
List list = session.createQuery("from Hx c order by c.name")
.list();
QBC方式
List list = session.createCriteria(Hx.class)
.add(Expression.like("name","z%"))
.addOrder(Order.desc("name"))
.list();
分页查询
Query和Criteria接口都提供了用于分页显示查询结果的方法:
setFirstResult(int firstResult):设定从哪一个对象开始检索,参数firstResult表示这个对象在查询结果中的索引位置,索引位置的起始值为0。默认情况下,Query和Criteria接口从查询结果中的第一个对象,也就是索引位置为0的对象开始检索。
setMaxResult(int maxResults):设定一次最多检索出的对象数目。默认情况下,Query和Criteria接口检索出查询结果中所有的对象。
分页查询
//采用HQL检索方式
Query query = session.createQuery("from
Customer c
order by c.name asc");
query.setFirstResult(0);
query.setMaxResults(10);
List result = query.list();
//采用QBC检索方式
Criteria criteria = session.createCriteria(
Customer.class);
criteria.addOrder(
Order.asc("name") );
criteria.setFirstResult(0);
criteria.setMaxResults(10);
List result = criteria.list();
链索查询
List list = session.createQuery("from Hx")
.setFirstResult(0)
.setMaxResults(2)
.list();
List list = session.createCriteria(Hx.class)
.setFirstResult(0)
.setMaxResults(2)
.list();
检索单个对象
Query和Criteria都提供了返回单个对象的方法uniqueResult().
先调用setMaxResult(1)方法,把最大检索数目设为1,在调用uniqueResult()方法。
Hx hx = (Hx)session.createQuery("from Hx")
.setMaxResults(1)
.uniqueResult();
Hx hx = (Hx)session.createCriteria(Hx.class)
.addOrder(Order.asc("name"))
.setMaxResults(1)
.uniqueResult();
与对象属性绑定
Hx hx = new Hx();
hx.setAge("33");
List list = session.createQuery("from Hx as c where c.age=:age")
.setProperties(hx)
.list();
SQL内连接
内连接就是传统的连接操作,用join连接关联表,on作为连接条件,where指定其他限定条件的查询
如:
select hx.name,hx.age,hxhome.home from hx join hxhome on hx.id=hxhome.hxid
SQL左外连接
在结果表中包含第一个表中满足的所有纪录,如果是在连接条件上匹配纪录,则第二个表返回相应的值,否则第二个表返回空值。
如:
select hx.name,hx.age,hxhome.home from hx left join hxhome on hx.id=hxhome.hxid
SQL右外连接
在结果表中包含第二个表中满足的所有纪录,如果是在连接条件上匹配纪录,则第一个表返回相应的值,否则第一个表返回空值。
如:
select hx.name,hx.age,hxhome.home from hx right outer join hxhome on hx.id=hxhome.hxid
迫切左外连接
以下两种检索方式是等价的,它们都能同时迫切左外连接类B和类C:
//HQL迫切左外连接检索方式
from A a left join fetch a.b b left join fetch a.c c where b is not
null and c is not null
//QBC迫切左外连接检索方式
List result=session.createCriteria(A.class)
.setFetchMode("this.b",FetchMode.EAGER)
.setFetchMode("this.c",FetchMode.EAGER)
.add(Expression.isNotNull("this.b"))
.add(Expression.isNotNull("this.c"))
.list();
投影查询
select关键字用于选择对象的部分属性,例如:
Iterator it=session.createQuery(
"select c.id,c.name,o.orderNumber "
+ " from Customer c join c.orders o "
+" where o.orderNumber like 'T%'" ).list().iterator();
while(it.hasNext()){
Object[] row=(Object[])it.next();
Long orderNumber=(String)row[2];
System.out.println(id+" "+name+" "+orderNumber);
}
投影查询
HQL查询语句对应的SQL语句为:
select c.ID,c.NAME,o.ORDER_NUMBER
from CUSTOMERS c inner join ORDERS o
on c.ID=o.CUSTOMER_ID where o.ORDER_NUMBER like 'T%';
以上查询语句的查询结果如下:
+----+------+--------------+
| ID | NAME | ORDER_NUMBER |
+----+------+--------------+
| 1 | Tom | Tom_Order001 |
| 1 | Tom | Tom_Order002 |
| 1 | Tom | Tom_Order003 |
+----+------+--------------+
Query的list()方法返回的集合中包含三个对象数组类型的元素,每个对象数组代表以上查询结果的一条记录。
类级别和关联级别可选的检索策略和默认的检索策略
检索策略的作用域 |
可选的检索策略 |
默认的检索策略 |
运行时行为受影响的sesssion的检索方法 |
类级别 |
立即检索
延迟检索 |
立即检索 |
仅影响load()方法 |
关联级别 |
立即检索
延迟检索
迫切左外连接检索 |
多对一和一对一关联为外连接检索 |
影响load(),get(),find()方法 |
一对多和多对多关联为立即检索 |
三种检索策略的运行机制
检索策略的类型 |
类级别 |
关联级别 |
优点 |
缺点 |
优先考虑使用的场合 |
立即检索 |
立即加载检索方法指定的对象 |
立即加载与检索方法指定的对象关联的对象,可以设定批量检索数量 |
对应用程序完全透明,不管对象处于持久化状态,还是游离状态,应用程序都可以方便地从一个对象导航到与它关联的对象 |
(1)select语句数目多;(2)可能会加载应用程序不需要访问的对象,造成内存空间的浪费 |
(1)类级别(2)应用程序需要立即访问的对象(3)使用了二级缓存 |
延迟检索 |
延迟加载检索方法指定的对象 |
延迟加载与检索方法指定的对象,可以设定批量检索数量 |
由应用程序决定需要加载那些对象,可以避免执行多余的select语句,以及避免加载应用程序不需要访问的对象。因此提高检索性能,并能节省内存空间 |
应用程序如果希望访问游离状态的代理类实例,必须保证它在持久化状态时已经被初始化 |
(1)一对多或多对多关联(2)应用程序不需要立即访问或者根本不会访问的对象 |
迫切左外连接检索 |
不适用 |
通过左外连接加载与检索方法指定的对象 |
(1)对应用程序完全透明,不管对象处于持久化状态,还是游离状态,应用程序都可以方便地从一个对象导航到与它关联的对象(2)使用了外连接,select语句数目少 |
(1)可能会加载应用程序不需要访问的对象,造成内存空间的浪费(2)复杂的数据表连接也会影响检索性能 |
(1)多对一或一对一关联(2)应用程序需要立即访问的对象(3)数据库系统具有良好的表连接性能 |
映射文件中用于设定检索策略的几个属性
属性 |
可选值 |
默认值 |
描述 |
lazy |
true或false |
hibernate2.x版本为false
hibernate3.x版本为true |
如果为true,表示使用延迟策略。在和中包含此属性 |
outer-join |
auto、true或false |
在和元素中为auto;在元素中为false |
如果为true,表示使用迫切左外连接检索。在、和元素中包含此属性 |
batch-size |
正整数 |
1 |
设定批量检索的数量。如果设定此项,合理的取值在3~10之间。仅适用于关联级别的立即检索和延迟检索,在和元素中包含此属性 |
Set元素的lazy和outer-join属性
lazy属性 |
outer-join属性 |
检索策略 |
false |
true |
采用立即检索,这是默认的检索策略,当使用hibernate二级缓存可以考虑使用立即检索 |
false |
false |
采用迫切左外连接检索。对于hibernate2.x版本,在映射文件中如果有多个元素,只允许有一个元素的outer-join属性为true |
true |
false |
采用延迟检索。这是优先考虑的检索策略 |
true |
true |
没有任何意义 |
设置多对一关联的检索策略
(以客户和订单为例)
Order.hbm.xml的元素的outer-join属性 |
Customer.hbm.xml的元素的lazy属性 |
检索order对象时,对关联的customer对象使用的检索策略 |
auto |
true |
延迟检索 |
auto |
false |
迫切左外连接检索 |
true |
true |
迫切左外连接检索 |
true |
false |
迫切左外连接检索 |
false |
true |
延迟检索 |
false |
false |
立即检索 |
注:
1默认情况下,Hibernate 3对集合使用延迟select抓取,对返回单值的关联使用延迟代理抓取。
2在Hibernate2.1中,lazy属性的默认值为“false”,而在Hibernate3.0中,lazy属性的默认值为“true”。
3FetchMode.LAZY 和 FetchMode.EAGER被废弃。取而代之的分别为FetchMode.SELECT 和FetchMode.JOIN。
阅读(590) | 评论(0) | 转发(0) |