Hibernate 3 引入 Filter(過濾器),類似資料庫 View 但可在應用層動態啟用、帶參數。定義於映射檔,運行時由 Session 啟用,自動在查詢 SQL 中附加條件。適用於多租戶、軟刪除、時效性資料等橫切關注點。
在 <hibernate-mapping> 內定義:
<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 session = ...;
session.enableFilter("myFilter").setParameter("myFilterParam", "some-value");
// 支援鏈式呼叫
預設不啟用,需顯式 enableFilter。getEnabledFilter 取得實例,disableFilter 關閉。
員工/部門資料含生效起迄日,僅查詢「目前生效」記錄:
<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.enableFilter("effectiveDate").setParameter("asOfDate", new Date());
List results = session.createQuery(
"from Employee e where e.salary > :targetSalary")
.setLong("targetSalary", 1000000L)
.list();
雖然 HQL 僅有薪水條件,實際 SQL 會自動附加:
WHERE salary > 1000000
AND CURRENT_DATE BETWEEN eff_start_dt AND eff_end_dt
搭配外連接時,條件表達式方向(左/右)影響語意。最安全寫法:
:param OPERATOR column(參數在左、欄位在右)tenant_id = :currentTenantdeleted = false 或 deleted_at IS NULLFilter 將重複的 Where 條件集中化、參數化、動態化,避免在每個 Query/DAO 中硬編碼。關鍵在於:定義於映射層、啟用於 Session、參數化條件。善用可大幅減少 DAO 代碼,確保橫切條件一致性。