Hibernate之DetachedCriteria类详解

Hibernate之DetachedCriteria类详解

首先看DetachedCriteria这个类名,是由两个单词(detached和criteria)组成的,Criteria咱们知道是QBC查询主要接口之一,它通过组装各种Criterion对象来获取实体,Hibernate中的Session是产生Criteria的工厂,Criterion实例一般来说都是通过Restrictions类获取的,如下面这个例子:

[java]  view plain  copy
  1. List cats = session.createCriteria(Cat.class)  
  2.     .add( Restrictions.like("name""Iz%") )  
  3.     .add( Restrictions.gt( "weight"new Float(minWeight) ) )  
  4.     .addOrder( Order.asc("age") )  
  5.     .list();  
通过上述例子可以发现需要使用Session实例来获取Criteria对象,再看另外一个单词detached,意思为“分离的、分开的、分割的、未绑定依附的”意思,那到底跟谁分离、分开呢?对,就是session,也就是说两个单词合起来的意思是该类除了创建时不在依附于任何Session,但可以完整支持Criteria的功能,这就是DetachedCriteria的诞生的根本需求;

下面咱们再来讨论下该类的应用场景:

在常规的Web编程中,有大量的动态条件查询,即用户在网页上面根据自身需要选择录入某些条件,程序根据用户选择内容,动态生成查询SQL语句,进行查询。
  针对这种需求,对于分层应用程序来说,Web层需要传递一个包含了查询的条件条件的列表给业务层对象(传统上使用Map对象),业务层对象获得这个条件列表之后,依次从列表取出条件,构造查询语句。这里的一个难点是条件列表用什么来构造?那么这么做的缺陷就是Map对象可以传递的信息非常有限,只能传递name和value,无法传递究竟要做怎样的条件运算,即这么name和value之间什么关系,是>,<,IN,AND,OR呢?这就要求业务层对象必须确切掌握每条entry的隐含条件。因此一旦隐含条件改变,业务层对象的查询构造算法必须相应修改,但是这种查询条件的改变是隐式约定的,而不是程序代码约束的,因此非常容易出错。
DetachedCriteria的出现解决了上述问题;

下面介绍一下DetachedCriteria的日常使用;

1、DetachedCriteria类允许你在Hibernate的Session范围外创建一个查询,然后使用任意一个Session环境去执行它,这种用法也是使用最多的用法,该类提供了如下两个方法用以构建DetachedCriteria对象


代码如下:

[java]  view plain  copy
  1. // 创建DetachedCriteria对象  
  2. DetachedCriteria query = DetachedCriteria.forClass(Cat.class).add( Property.forName("sex").eq('F') );  
  3. // 获取Session对象  
  4. Session session = ....;  
  5. // 开启事务  
  6. Transaction txn = session.beginTransaction();  
  7. // 将DetachedCriteria查询对象与可执行的Criteria实例关联起来  
  8. List results = query.getExecutableCriteria(session).setMaxResults(100).list();  
  9. // 提交事务  
  10. txn.commit();  
  11. // 关闭Session,释放资源  
  12. session.close();  
2、一个DetachedCriteria可用作子查询,Criterion实例可以通过Subqueries和Property类调用DetachedCriteria构建的子查询,如下代码所示:

[java]  view plain  copy
  1. // 构建所有Cat中的平均体重  
  2. DetachedCriteria avgWeight = DetachedCriteria.forClass(Cat.class)  
  3.         .setProjection(Property.forName("weight").avg());  
  4. // 获取所有Cat中,高于平均提供的Cat的集合  
  5. session.createCriteria(Cat.class).add(Property.forName("weight").gt(avgWeight))  
  6.         .list();  
[java]  view plain  copy
  1. // 构建所有Cat的提供集合列表  
  2. DetachedCriteria weights = DetachedCriteria.forClass(Cat.class)  
  3.         .setProjection(Property.forName("weight"));  
  4. // 获取所有Cat中,体重最大的Cat  
  5. session.createCriteria(Cat.class).add(Subqueries.geAll("weight", weights))  
  6.         .list();  
  7. }  
关联子查询,即DetachedCriteria构建的子查询和Criteria构建的查询也可以直接交互,如下:

[java]  view plain  copy
  1. DetachedCriteria avgWeightForSex = DetachedCriteria.forClass(Cat.class"cat2")  
  2.         .setProjection(Property.forName("weight").avg()).add(Property.forName("cat2.sex").eqProperty(  
  3.                 "cat.sex"));  
  4. session.createCriteria(Cat.class,"cat").add(Property.forName("weight").gt(avgWeightForSex)).list();  
最后在上一个当用DetachedCriteria构建的投影,有多个列的例子:

[java]  view plain  copy
  1. DetachedCriteria sizeQuery = DetachedCriteria  
  2.         .forClass(SlEmployee.class).setProjection(Projections.projectionList()  
  3.                 .add(Projections.property("userName"))  
  4.                 .add(Projections.property("employeeName")))  
  5.                 .add(Restrictions.eq("userName""CHENGYU"));  
  6. List list = session.createCriteria(SlEmployee.class)  
  7.         .add(Subqueries.propertiesEq(new String[] { "userName""employeeName" }, sizeQuery)).list();  
实际项目中用的最多的是第一种用法,即用来构建一个查询对象,对于子查询这种用法则用的较少,通过例子可以看出,子查询的功能似乎才更能体现出DetachedCriteria的强大!!

你可能感兴趣的:(JavaEE)