`
envoydada
  • 浏览: 65362 次
社区版块
存档分类
最新评论

Hibernate3支持DetachedCriteria(转贴)

阅读更多
Hibernate3支持DetachedCriteria,这是一个非常有意义的特性!我们知道,在常规的Web编程中,有大量的动态条件查询,即用户在网页上面自由选择某些条件,程序根据用户的选择条件,动态生成SQL语句,进行查询。

  针对这种需求,对于分层应用程序来说,Web层需要传递一个查询的条件列表给业务层对象,业务层对象获得这个条件列表之后,然后依次取出条件,构造查询语句。这里的一个难点是条件列表用什么来构造?传统上使用Map,但是这种方式缺陷很大,Map可以传递的信息非常有限,只能传递name和value,无法传递究竟要做怎样的条件运算,究竟是大于,小于,like,还是其它的什么,业务层对象必须确切掌握每条entry的隐含条件。因此一旦隐含条件改变,业务层对象的查询构造算法必须相应修改,但是这种查询条件的改变是隐式约定的,而不是程序代码约束的,因此非常容易出错。

  DetachedCriteria可以解决这个问题,即在web层,程序员使用DetachedCriteria来构造查询条件,然后将这个DetachedCriteria作为方法调用参数传递给业务层对象。而业务层对象获得DetachedCriteria之后,可以在session范围内直接构造Criteria,进行查询。就此,查询语句的构造完全被搬离到web层实现,而业务层则只负责完成持久化和查询的封装即可,与查询条件构造完全解耦,非常完美!这恐怕也是以前很多企图在web层代码中构造HQL语句的人想实现的梦想吧!

  示例代码片段如下:

  web层程序构造查询条件:

  java代码:

DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Department.class);
detachedCriteria.add(Restrictions.eq("name", "department")).createAlias("employees", "e").add(Restrictions.gt(("e.age"), new Integer(20)));

  Department和Employee是一对多关联,查询条件为:

  名称是“department”开发部门;
  部门里面的雇员年龄大于20岁;

  业务层对象使用该条件执行查询:

  java代码:

detachedCriteria.getExecutableCriteria(session).list();

  最大的意义在于,业务层代码是固定不变的,所有查询条件的构造都在web层完成,业务层只负责在session内执行之。这样代码就可放之四海而皆准,都无须修改了。

  然而Spring和Hibernate3的DetachedCriteria有不兼容的问题,因此在Spring环境下面使用Hibernate3需要注意:

  Spring的HibernateTemplate提供了Hibernate的完美封装,即通过匿名类实现回调,来保证Session的自动资源管理和事务的管理。其中核心方法是:

  java代码:

HibernateTemplate.execute(new HibernateCallback() {
 public Object doInHibernate(Session session) throws HibernateException {
  ....
 }
}

  回调方法提供了session作为参数,有了session,就可以自由的使用Hibernate API编程了。使用了spring的之后,代码修改如下:

  web层代码:

  java代码:

DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Department.class);
detachedCriteria.createAlias("employees", "e").add(Restrictions.eq("name", "department")).add(Restrictions.gt(("e.age"), new Integer(20)));
departmentManager.findByCriteria(detachedCriteria);

  构造detachedCriteria,作为参数传递给departmentManager

  业务层代码使用spring,DepartmentManager的findByCriteria如下:

  java代码:

public List findByCriteria(final DetachedCriteria detachedCriteria) {
 return (List) getHibernateTemplate().execute(new HibernateCallback() {
  public Object doInHibernate(Session session) throws HibernateException {
   Criteria criteria = detachedCriteria.getExecutableCriteria(session);
   return criteria.list();
  }
 });
}

  实际上也就是:

  java代码:

Criteria criteria = detachedCriteria.getExecutableCriteria(session);
return criteria.list();

  而已

  但是该程序代码执行,会抛出强制类型转换异常!

  跟踪了一下spring和Hibernate源代码,原因如下:

  spring的HibernateTemplate的execute方法提供的回调接口具有Session作为参数,但是实际上,默认情况下,HibernateTemplate传递给回调接口的session并不是org.hibernate.impl.SessionImpl类,而是SessionImpl类的一个Proxy类。之所以替换成为一个Proxy类,HibernateTemplate的注释说明,Proxy提供了一些额外的功能,包括自动设置Cachable,Transaction的超时时间,Session资源的更积极的关闭等等。

  java代码:

private boolean exposeNativeSession = false;
...

  execute方法内部:

Session sessionToExpose = (exposeNativeSession ? session : createSessionProxy(session));

  但是遗憾的是,Hibernate的DetachedCriteria的setExecutableCriteria方法却要求将session参数强制转为SessionImpl,但是spring传过来的却是一个Proxy类,因此就报错了。

  java代码:

public Criteria getExecutableCriteria(Session session) {
 impl.setSession( (SessionImpl) session ); // 要求SessionImpl,Spring传递的是Proxy
 return impl;
}

  解决方法,禁止Spring的HibernateTemplate传递Proxy类,强制要求它传递真实的SessionImpl类,即给exexute方法增加一个参数,提供参数为true,如下:

  java代码:

public List findByCriteria(final DetachedCriteria detachedCriteria) {
 return (List) getHibernateTemplate().execute(new HibernateCallback() {
  public Object doInHibernate(Session session) throws HibernateException {
   Criteria criteria = detachedCriteria.getExecutableCriteria(session);
   return criteria.list();
  }
 }, true);
}
<script> var ad_cid; if (window.location.search.substring(1) != "") { ad_cid = window.location.search.substring(1); } else { ad_cid = 412; } </script>
                                //统计记录数
                                Criteria criteria 
= detachedCriteria.getExecutableCriteria(session); 
                                
int totalCount = ((Integer) criteria.setProjection(Projections.rowCount()).uniqueResult
分享到:
评论

相关推荐

    Hibernate - DetachedCriteria 的完整用法

    "Hibernate - DetachedCriteria 的完整用法" Hibernate 的 Criteria 和 DetachedCriteria 是两个不同的概念,虽然它们都是用于查询数据的,但它们在创建和使用上有所不同。 首先,Criteria 是在线的,需要通过 ...

    Hibernate 使用DetachedCriteria操作

    **Hibernate 框架及其DetachedCriteria操作详解** Hibernate 是一个强大的Java持久化框架,它极大地简化了数据库操作,使得开发者能够用面向对象的方式处理数据库事务。本篇将深入探讨Hibernate中的...

    Hibernate(24): 为什么用DetachedCriteria不能表连接地取数据?

    在Java的持久化框架Hibernate中,DetachedCriteria是一个强大的查询工具,它允许我们在不与Session交互的情况下构建查询条件。然而,DetachedCriteria在处理复杂的关联查询,尤其是涉及到表连接(JOIN)时,可能存在...

    Hibernate3中文文档

    10. **集合映射**:Hibernate支持多种集合类型(如List、Set、Map等)与数据库表之间的映射,以及一对一、一对多、多对多关系的处理。 11. **事件监听器**:Hibernate允许注册事件监听器,以便在特定的持久化操作...

    DetachedCriteria笔记

    DetachedCriteria

    hibernate3.zip

    10. **多对一、一对多、多对多关联映射**:Hibernate3支持多种关联关系的映射,包括单向、双向、级联操作等,使得数据库关系模型能够完整地映射到对象模型。 通过这个"hibernate3.zip"压缩包,你可以获取到完整的...

    DetachedCriteria查询

    DetachedCriteria 是 Hibernate 中的一种离线查询对象,它可以在不依赖 Session 的情况下生成动态 SQL 语句并进行查询。下面是 DetachedCriteria 查询的详细知识点: 创建 DetachedCriteria 对象 DetachedCriteria...

    Hibernate3.3 API中文版

    在查询语言上,Hibernate支持HQL(Hibernate Query Language),这是一种面向对象的查询语言,类似于SQL但操作的是对象而非表格。此外,`Criteria` API提供了一种类型安全的方式来构建动态查询,而`DetachedCriteria...

    hibernate3使用手册

    - Hibernate支持编程式和声明式事务管理,基于JTA或JDBC的Transaction API。 11. **Hibernate事件和监听器** - 可以注册监听器来捕获对象状态变化的事件,如对象加载、保存、更新、删除等。 12. **Hibernate的...

    Hibernate_3 api

    - Hibernate支持单表继承、联合继承和表-per-class继承策略,使得基于类的层次结构可以映射到数据库。 13. **集合映射**: - Hibernate提供了List、Set、Map、Bag等多种集合类型的映射,以便处理数据库中的关联...

    DetachedCriteria使用介绍

    `DetachedCriteria` 是 Hibernate 提供的一种灵活且强大的查询机制,它允许你在脱离 Session 的情况下构建复杂的查询标准,这意味着你可以提前构建查询标准,然后在任何地方执行查询,而无需关心当前是否有 Session...

    hibernate3源码

    12. **Callback事件**:Hibernate支持在对象生命周期中的某些关键点触发回调方法,如pre-update,post-insert等,便于实现特定业务逻辑。 13. **实体状态**:Hibernate3将对象分为瞬时态、持久态、脱管态和临时态,...

    Hibernate3.2_帮助文档

    9. **事务管理**:Hibernate支持JTA(Java Transaction API)和JDBC事务管理,确保数据的一致性和完整性。 10. **缓存机制**:Hibernate提供了第一级缓存(Session级别的缓存)和第二级缓存(SessionFactory级别的...

    Hibernate 3.2.0 中文官方文档

    9. **缓存机制**:Hibernate支持第二级缓存和查询缓存,可以显著提高性能。理解何时及如何使用缓存策略。 10. **事务管理**:学习如何在Hibernate中处理事务,包括自动提交、显式提交、回滚和隔离级别。 11. **...

    Hibernate3.2详细教程及课程笔记

    12. **继承映射**:Hibernate支持单表继承、联合继承和表格-per-class继承策略,学习者应了解每种策略的适用场景。 通过本教程的逐日学习,包括`day01`至`day07`的笔记内容,以及可能包含代码示例的`day03.txt`、`...

    hibernate-distribution中文帮助手册

    10. **事务处理**:Hibernate支持JTA和JDBC两种事务处理方式,保证数据的一致性和完整性。 11. **关联映射**:包括一对一、一对多、多对一、多对多四种关系映射,通过外键或中间表实现。 12. **懒加载与立即加载**...

    hibernate3.6.1源码

    10. **方言(Dialect)**:Hibernate支持多种数据库,`org.hibernate.dialect`包定义了各种数据库的方言,用于生成适应不同数据库的SQL。 通过阅读和理解Hibernate 3.6.1的源码,开发者不仅可以更好地掌握ORM的工作...

    hibernate5.1.10 依赖jar包

    Hibernate支持多种数据库,如MySQL、Oracle、PostgreSQL等,通过方言(Dialect)类适应不同数据库的SQL语法差异。 **10. JPA支持** Hibernate 5.1.10也支持Java Persistence API (JPA),这是Java EE规范的一部分,...

    Hibernate API Documentation 3.3.0.SP1

    1. One-to-One、One-to-Many和Many-to-Many关联:Hibernate支持多种对象间的关联映射,如一对一、一对多和多对多,通过@OneToOne、@OneToMany和@ManyToMany等注解实现。 2. Collections:Hibernate允许在实体类中...

    hibernate 3.5.5 常用jar包

    6. **事务管理**:Hibernate支持JTA(Java Transaction API)和JTASessionContext,以及JDBC级别的本地事务。`Transaction`接口用于开始、提交和回滚事务。 7. **查询语言(HQL)**:Hibernate Query Language是一...

Global site tag (gtag.js) - Google Analytics