1. 程式人生 > 其它 >Java中使用Hibernate系列之過濾器(filters)學習

Java中使用Hibernate系列之過濾器(filters)學習

Hibernate3新增了對某個類或者集合使用預先定義的過濾器條件(filter criteria)的功能。過濾器條件相當於定義一個 非常類似於類和各種集合上的“where”屬性的約束子句,但是過濾器條件可以帶引數。 應用程式可以在執行時決定是否啟用給定的過濾器,以及使用什麼樣的引數值。 過濾器的用法很像資料庫檢視,只不過是在應用程式中確定使用什麼樣的引數的。

網路配圖

要使用過濾器,必須首先在相應的對映節點中定義。而定義一個過濾器,要用到位於<hibernate-mapping/> 節點之內的<filter-def/>節點:

<filter-def name="myFilter"><filter-param name="myFilterParam" type="string"/></filter-def>

定義好之後,就可以在某個類中使用這個過濾器:

<class name="myClass" ...>...<filter name="myFilter" condition=":myFilterParam = MY_FILTERED_COLUMN"/></class>

也可以在某個集合使用它:

<set ...><filter name="myFilter" condition=":myFilterParam = MY_FILTERED_COLUMN"/></set>

可以在多個類或集合中使用某個過濾器;某個類或者集合中也可以使用多個過濾器。

Session物件中會用到的方法有:enableFilter(String filterName), getEnabledFilter(String filterName), 和 disableFilter(String filterName). Session中預設是不啟用過濾器的,必須通過Session.enabledFilter()方法顯式的啟用。 該方法返回被啟用的Filter的例項。以上文定義的過濾器為例:

session.enableFilter("myFilter").setParameter("myFilterParam", "some-value");

注意,org.hibernate.Filter的方法允許鏈式方法呼叫。(類似上面例子中啟用Filter之後設定Filter引數這個“方法鏈”) Hibernate的其他部分也大多有這個特性。

下面是一個比較完整的例子,使用了記錄生效日期模式過濾有時效的資料:

<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"/>...<!--Note that this assumes non-terminal records have an eff_end_dt set toa max db date for simplicity-sake注意,為了簡單起見,此處假設僱用關係生效期尚未結束的記錄的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中,雖然我們僅僅顯式的使用了一個薪水條件,但因為啟用了過濾器,查詢將僅返回那些目前僱用 關係處於生效期的,並且薪水高於一百萬美刀的僱員的資料。

注意:如果你打算在使用外連線(或者通過HQL或load fetching)的同時使用過濾器,要注意條件表示式的方向(左還是右)。 最安全的方式是使用左外連線(left outer joining)。並且通常來說,先寫引數, 然後是操作符,最後寫資料庫欄位名。

在Filter定義之後,它可能被附加到多個實體和/或集合類,每個都有自己的條件。假若這些條件都是一樣的,每次都要定義就顯得很繁瑣。因此,<filter-def/>被用來定義一個預設條件,它可能作為屬性或者CDATA出現:

<filter-def name="myFilter" condition="abc > xyz">...</filter-def><filter-def name="myOtherFilter">abc=xyz</filter-def>

當這個filter被附加到任何目的地,而又沒有指明條件時,這個條件就會被使用。注意,換句話說,你可以通過給filter附加特別的條件來過載預設條件。