數(shù)據(jù)過濾并不是一種常規(guī)的數(shù)據(jù)查詢方法,而是一種整體的篩選方法。數(shù)據(jù)過濾也可對(duì)數(shù)據(jù)進(jìn)行篩選,因此,將其放在Hibernate的數(shù)據(jù)查詢框架中介紹。
如果一旦啟用了數(shù)據(jù)過濾器,則不管數(shù)據(jù)查詢,還是數(shù)據(jù)加載,該過濾器將自動(dòng)作用于所有數(shù)據(jù),只有滿足過濾條件的記錄才會(huì)被選出來。
過濾器與定義在類和集合映射文件上的“where”屬性非常相似。它們的區(qū)別是過濾器可以帶參數(shù),應(yīng)用程序可以在運(yùn)行時(shí)決定是否啟用指定的過濾器,以及使用什么樣的參數(shù)值。而映射文件上的“where”屬性將一直生效,且無法動(dòng)態(tài)傳入?yún)?shù)。
過濾器的用法很像數(shù)據(jù)庫視圖,區(qū)別是視圖在數(shù)據(jù)庫中已經(jīng)定義完成,而過濾器則還需在應(yīng)用程序中確定參數(shù)值。
過濾器的使用分成三步:
(1)定義過濾器。使用filter-def元素定義過濾器;
(2)使用過濾器。使用filter元素使用過濾器;
(3)在代碼中啟用過濾器。
前兩個(gè)步驟都是在Hibernate的映射文件中完成的,其中filter-def是hibernate-mapping元素的子元素,而filter元素是class集合元素的子元素。
filter-def元素用于定義一個(gè)過濾器,filter則將指定的過濾器應(yīng)用到指定的持久化類。
一個(gè)持久化類或集合可以使用多個(gè)過濾器,而一個(gè)過濾器也可以作用于多個(gè)持久化類或集合。
看下面的映射文件示例:
<?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 >
??? <!-- 每個(gè)class元素定義一個(gè)持久化類 -->
??? <class name="Category" table="category">
??????? <!-- 定義標(biāo)識(shí)屬性 -->
??? ??? <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關(guān)聯(lián)屬性 -->
??? ??? <set cascade="none" inverse="true" name="products"
??????? table="product_category">
??????????? <!-- 定義關(guān)聯(lián)屬性的key,對(duì)應(yīng)連接表中的外鍵列 -->
??????? ??? <key column="category_id"/>
??????????? <!-- 定義關(guān)聯(lián)屬性 -->
??????? ??? <many-to-many column="product_id" class="Product"/>
??? ??? </set>
??????? <!-- 使用過濾器,并設(shè)置過濾器條件 -->
??? ??? <filter name="effectiveDate" condition=":asOfDate BETWEEN
??????? eff_start_date and eff_end_date"/>
??? </class>
??? <!-- 定義第二個(gè)持久化類 -->
??? <class name="Product" table="product">
??????? <!-- 定義標(biāo)識(shí)屬性 -->
??? ??? <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關(guān)聯(lián)屬性 -->
??????? <set cascade="all" name="categories" fetch="join"
??????? table="product_category" >
??????????? <!-- 定義關(guān)聯(lián)屬性的key,對(duì)應(yīng)連接表中的外鍵列 -->
??????? ??? <key column="product_id"/>
??????????? <!-- 定義關(guān)聯(lián)屬性 -->
??????? ??? <many-to-many column="category_id"
??????????????????????? class="Category" fetch="join">
??????????????? <!-- 對(duì)關(guān)聯(lián)屬性使用第一個(gè)過濾器 -->
??? ??????????? <filter name="effectiveDate"
??????????????????? condition=":asOfDate BETWEEN eff_start_date and
??????????????????? eff_end_date"/>
??????????????? <!-- 對(duì)關(guān)聯(lián)屬性使用第二個(gè)過濾器 -->
??????????? ??? <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>
??? <!-- 定義第一個(gè)過濾器,該過濾器包含一個(gè)date類型的參數(shù) -->
??? <filter-def name="effectiveDate">
??????? <filter-param name="asOfDate" type="date"/>
??? </filter-def>
??? <!-- 定義第二個(gè)過濾器,該過濾器包含一個(gè)long類型的參數(shù) -->
??? <filter-def name="category">
??????? <filter-param name="catId" type="long"/>
??? </filter-def>
</hibernate-mapping>
在上面的配置文件中,定義了兩個(gè)過濾器,過濾器的定義通過filter-def元素完成。定義過濾器時(shí),只需要指定過濾器的名字,以及過濾器的參數(shù)即可。如Java里的一個(gè)方法聲明,只有方法名和參數(shù)列表,具體的方法實(shí)現(xiàn)是沒有的。
過濾器的過濾條件是使用過濾器時(shí)才確定的,使用過濾器通過filter元素確定,filter的condition屬性用于確定過濾條件,滿足該條件的記錄才會(huì)被抓取到。
系統(tǒng)默認(rèn)不啟用過濾器,必須顯式通過enableFilter(String filterName)才可以啟用過濾器,該方法返回一個(gè)Filter實(shí)例,F(xiàn)ilter包含setParameter方法用于為過濾器參數(shù)賦值。
一旦啟用了過濾器,過濾器在整個(gè)Session內(nèi)有效,所有的數(shù)據(jù)加載將自動(dòng)應(yīng)用該過濾條件,直到調(diào)用disableFilter方法。
看下面的使用過濾器的示例代碼:
private void test() throws Exception
{
??? //獲取Hibernate Session對(duì)象
??? Session session = HibernateUtil.currentSession();
??? //開始事務(wù)
??? Transaction tx = session.beginTransaction();
??? //啟用第一個(gè)過濾器
??? session.enableFilter("effectiveDate")
??????????? //為過濾器設(shè)置參數(shù)
??????????? .setParameter("asOfDate", new Date());
??? //啟動(dòng)第二個(gè)過濾器
??? session.enableFilter("category")
??????????? //為過濾器設(shè)置參數(shù)
??????????? .setParameter("catId", new Long(2));
??? //執(zhí)行查詢,該查詢沒有任何的查詢條件
??? Iterator results = session.createQuery("from Product as p")
????????????????????????? .iterate();
??? //遍歷結(jié)果集
??? while (results.hasNext())
??? {
??????? Product p = (Product)results.next();
??????? System.out.println(p.getName());
??????? //此處獲取Product關(guān)聯(lián)的種類,過濾器也將自動(dòng)應(yīng)用過濾
??????? 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();
}
通過使用過濾器定義常用的數(shù)據(jù)篩選規(guī)則,如果是臨時(shí)的數(shù)據(jù)篩選,還是使用常規(guī)查詢比較好。對(duì)于從前使用行列表達(dá)式視圖的地方,此處可以考慮使用過濾器。
posted on 2009-07-19 09:08
jadmin 閱讀(117)
評(píng)論(0) 編輯 收藏