风故故,也依依

Stand still in the wind.

导航

统计

公告

Hibernate的数据过滤查询

数据过滤并不是一种常规的数据查询方法,而是一种整体的筛选方法。数据过滤也可对数据进行筛选,因此,将其放在Hibernate的数据查询框架中介绍。

如果一旦启用了数据过滤器,则不管数据查询,还是数据加载,该过滤器将自动作用于所有数据,只有满足过滤条件的记录才会被选出来。

过滤器与定义在类和集合映射文件上的“where”属性非常相似。它们的区别是过滤器可以带参数,应用程序可以在运行时决定是否启用指定的过滤器,以及使用什么样的参数值。而映射文件上的“where”属性将一直生效,且无法动态传入参数。

过滤器的用法很像数据库视图,区别是视图在数据库中已经定义完成,而过滤器则还需在应用程序中确定参数值。

过滤器的使用分成三步:

(1)定义过滤器。使用filter-def元素定义过滤器;

(2)使用过滤器。使用filter元素使用过滤器;

(3)在代码中启用过滤器。

前两个步骤都是在Hibernate的映射文件中完成的,其中filter-def是hibernate-mapping元素的子元素,而filter元素是class集合元素的子元素。

filter-def元素用于定义一个过滤器,filter则将指定的过滤器应用到指定的持久化类。

一个持久化类或集合可以使用多个过滤器,而一个过滤器也可以作用于多个持久化类或集合。

看下面的映射文件示例:

<?xml version="1.0"?>

<!-- Hibernate配置文件的文件头,包含DTD等信息 -->

<!DOCTYPE hibernate-mapping

    PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<!-- Hibernate 配置文件的根元素 -->

<hibernate-mapping >

    <!-- 每个class元素定义一个持久化类 -->

    <class name="Category" table="category">

        <!-- 定义标识属性 -->

        <id name="id" column="category_id" >

            <!-- 指定主键生成器策略 -->

            <generator class="native"/>

        </id>

        <!-- 映射name属性 -->

        <property name="name" type="string"/>

        <!-- 映射effectiveStartDate属性 -->

        <property name="effectiveStartDate" column="eff_start_date"

        type="java.util.Date"/>

        <!-- 映射effectiveEndDate属性 -->

        <property name="effectiveEndDate" column="eff_end_date"

        type="java.util.Date"/>

        <!-- 映射N-N关联属性 -->

        <set cascade="none" inverse="true" name="products"

        table="product_category">

            <!-- 定义关联属性的key,对应连接表中的外键列 -->

            <key column="category_id"/>

            <!-- 定义关联属性 -->

            <many-to-many column="product_id" class="Product"/>

        </set>

        <!-- 使用过滤器,并设置过滤器条件 -->

        <filter name="effectiveDate" condition=":asOfDate BETWEEN

        eff_start_date and eff_end_date"/>

    </class>

    <!-- 定义第二个持久化类 -->

    <class name="Product" table="product">

        <!-- 定义标识属性 -->

        <id name="id" column="product_id" >

            <!-- 指定主键生成器策略 -->

            <generator class="native"/>

        </id>

        <!-- 映射name属性 -->

        <property name="name" type="string"/>

        <!-- 映射stockNumber属性 -->

        <property name="stockNumber" column="stock_number" type="int"/>

        <!-- 映射effectiveStartDate属性 -->

        <property name="effectiveStartDate" column="eff_start_date"

        type="java.util.Date"/>

        <!-- 映射effectiveEndDate属性 -->

        <property name="effectiveEndDate" column="eff_end_date"

        type="java.util.Date"/>

        <!-- 映射N-N关联属性 -->

        <set cascade="all" name="categories" fetch="join"

        table="product_category" >

            <!-- 定义关联属性的key,对应连接表中的外键列 -->

            <key column="product_id"/>

            <!-- 定义关联属性 -->

            <many-to-many column="category_id"

                        class="Category" fetch="join">

                <!-- 对关联属性使用第一个过滤器 -->

                <filter name="effectiveDate"

                    condition=":asOfDate BETWEEN eff_start_date and

                    eff_end_date"/>

                <!-- 对关联属性使用第二个过滤器 -->

                <filter name="category" condition="category_id = :catId"/>

            </many-to-many>

        </set>

        <filter name="effectiveDate" condition=":asOfDate BETWEEN

        eff_start_date AND eff_end_date"/>

    </class>

    <!-- 定义第一个过滤器,该过滤器包含一个date类型的参数 -->

    <filter-def name="effectiveDate">

        <filter-param name="asOfDate" type="date"/>

    </filter-def>

    <!-- 定义第二个过滤器,该过滤器包含一个long类型的参数 -->

    <filter-def name="category">

        <filter-param name="catId" type="long"/>

    </filter-def>

</hibernate-mapping>

在上面的配置文件中,定义了两个过滤器,过滤器的定义通过filter-def元素完成。定义过滤器时,只需要指定过滤器的名字,以及过滤器的参数即可。如Java里的一个方法声明,只有方法名和参数列表,具体的方法实现是没有的。

过滤器的过滤条件是使用过滤器时才确定的,使用过滤器通过filter元素确定,filter的condition属性用于确定过滤条件,满足该条件的记录才会被抓取到。

系统默认不启用过滤器,必须显式通过enableFilter(String filterName)才可以启用过滤器,该方法返回一个Filter实例,Filter包含setParameter方法用于为过滤器参数赋值。

一旦启用了过滤器,过滤器在整个Session内有效,所有的数据加载将自动应用该过滤条件,直到调用disableFilter方法。

看下面的使用过滤器的示例代码:

private void test() throws Exception

{

    //获取Hibernate Session对象

    Session session = HibernateUtil.currentSession();

    //开始事务

    Transaction tx = session.beginTransaction();

    //启用第一个过滤器

    session.enableFilter("effectiveDate")

            //为过滤器设置参数

            .setParameter("asOfDate", new Date());

    //启动第二个过滤器

    session.enableFilter("category")

            //为过滤器设置参数

            .setParameter("catId", new Long(2));

    //执行查询,该查询没有任何的查询条件

    Iterator results = session.createQuery("from Product as p")

                          .iterate();

    //遍历结果集

    while (results.hasNext())

    {

        Product p = (Product)results.next();

        System.out.println(p.getName());

        //此处获取Product关联的种类,过滤器也将自动应用过滤

        Iterator it = p.getCategories().iterator();

        System.out.println(p.getCategories().size());

        while (it.hasNext())

        {

            Category c = (Category)it.next();

            System.out.println(c.getName());

        }

    }

    tx.commit();

    HibernateUtil.closeSession();

}

通过使用过滤器定义常用的数据筛选规则,如果是临时的数据筛选,还是使用常规查询比较好。对于从前使用行列表达式视图的地方,此处可以考虑使用过滤器。

posted on 2009-07-19 09:08 jadmin 阅读(...) 评论(...) 编辑 收藏