Hibernate 过滤器
Hibernate过滤器(filter)是全局有效的、具有名字、可以带参数的过滤器,对于某个特定的Hibernate session您可以选择是否启用(或禁用)某个过滤器。
Hibernate3的过滤器可以进行预定义,并可绑定在类和集合层。那么什么叫预定义过滤器呢?就是可以定义象"where"子句的限制性子句,但这些 子句是相对类和不同集合的元素的。除了这些过滤器条件可以被参数化外。系统还能决定在运行是指定的过滤器是否应该被打开以及什么值被传入过滤器参数。
过滤器的配置:
为了使用过滤器,它们需要首先被定义,然后和响应的元素绑定。为了定义一个过滤器,我们将使用<hibernate-mapping/>中的<filter-def/>元素来定义Hibernate过滤器。如下所示:
<filter-def name="myFilter"> <filter-param name="myFilterParam" type="string"/> </filter-def> |
然后我们将这个过滤器附着在一个类上,如下所示:
<class name="myClass" ...> ... <filter name="myFilter" condition=":myFilterParam = my_filtered_column"/> </class> 或者是 <filter name="filtertest" condition="id < :myid"/> < 是小于 |
或附着在一个集合上。
<set ...> <filter name="myFilter" condition=":myFilterParam = my_filtered_column"/> 或者是 <filter name="filtertest" condition="id < :myid"/> < 是小于 </set> |
这里面的配置相当于在HQL语句中写上where id<:myid
当然,我们也可以两者皆有。
过滤器的用法:
为 了支持新过滤器,Hibernate3.x中新添加了一个接口:org.hibernate.Filter,以及在 org.hibernate.Session中加入了一些新方法。在Session中的新方法有:enableFilter(String filterName), getEnabledFilter(String filterName),以及disableFilter(String filterName)。在默认性况下,对于当前的会话,过滤器是关闭的。它们必须使用session的enableFilter()方法来显式地打开过 滤器。这个方法返回一个新过滤器的实例。按着上述的做法,我们可以用如下的代码打开过滤器:
session.enableFilter("myFilter").setParameter("myFilterParam", "some-value"); |
过滤大数据集
对于Hibernate3.x以前的版本,处理大数据集必须要使用大量的代码。为了达到目的,必须先将整个数据集装到内存中,然后对这个数据集使用session的filter()方法来过滤。而且当过滤实体时,我们必须手工写全部的HQL或一个定制的拦截器。
而在Hibernate3.x中提供了一种更简捷,更一致的方法来过滤数据。Hibernate设计街头团队想用一个更有效的特性来处理每一件事,无论它们是国际化的还是本地数据,或是为了安全考虑以及其他的事。现在让我们看一个例子来解释这一切。
现在假设有一个实体,这个实体跟着“有效的记录”数据库模式。这个实体有多个行,每一行都根据日期不同而不同,也就是说在日期范围内是有效的。一个 employment记录将是一个非常好的例子,因为employees可以来或去或再回来。现在我们开发一个带UI的程序,这个程序需要处理 employment数据的当前记录。为了使用新的过滤器特性达到这个目的。我们首先需要定义这个过滤器,然后将它附着在Employee类上。
<filter-def name="effectiveDate"> <filter-param name="asOfDate" type="date"/> </filter-def> <class name="Employee" ...> ... <many-to-one name="department" column="dept_id" class="Department"/> <property name="effectiveStartDate" type="date" column="eff_start_dt"/> <property name="effectiveEndDate" type="date" column="eff_end_dt"/> ... <filter name="effectiveDate" condition=":asOfDate BETWEEN eff_start_dt and eff_end_dt"/> </class> <class name="Department" ...> ... <set name="employees" lazy="true"> <key column="dept_id"/> <one-to-many class="Employee"/> <filter name="effectiveDate" condition=":asOfDate BETWEEN eff_start_dt and eff_end_dt"/> </set> </class> |
然后,为了保证总是加在到当前的有效记录。只要简单地将过滤器打开即可,代码如下:
Session session = ...; session.enabledFilter("effectiveDate").setParameter("asOfDate", new Date()); List results = session.createQuery("from Employee as e where e.salary > :targetSalary") .setLong("targetSalary", new Long(1000000)) .list(); |
在上面的HQL中,即使我们只给出一个salary约束条件,由于我们已经打开发过滤器,也只会得到当前活动的比一百万多的雇员。
一个简单 的filter 配置过程如下:
1. 在映射文件中定义过滤器的参数
<filter-def name="filtertest">
<filter-param name="myid" type="integer"/>
</filter-def>
在这个配置里,filter-param标签就是用来定义过滤器参数的
2. 在类的映射中使用这些参数
<filter name="filtertest" condition="id <:myid"/>
也就是是说,这个过滤器可以拿到其他的映射文件里,只是这些过滤器的名字不可以重复的。
3. 在程序中启用过滤器。
session.enableFilter("filtertest").setParameter("myid",Integer.valueOf("10");这样session
会自动将我们的过滤器条件加到我们的HQL查询语句的后面,相当于加上了where关键字在HQL查询语句。