View RSS Feed

My Java Tips

Hibernate Filters

Rate this Entry
by , 10-21-2011 at 07:40 PM (2596 Views)
A Hibernate filter is a global, named, parameterized filter that may be enabled or disabled for a particular Hibernate session. Filters can be used like database views.




Filters were introduced in Hibernate3. Using filters, you can define filter criteria and attach those filters at class and a collection level. A filter criteria is actually defining a restriction clause. This is same as "where" attribute available on the class and various collection elements. Thing to note is that filter conditions can be parameterized.

Application makes the decision at runtime whether given filters should be enabled and what their parameter values should be.

Filters must first be defined and then attached to the appropriate mapping elements.

Use the element within a element:
Java Code:
<pre lang="java">
<filter-def name="myFilter">

<filter-param name="myFilterParam" type="string">

</filter-param></filter-def></pre>

Following snippet shows how to attach filter to a class:
Java Code:
<pre lang="java">
<class name="myClass">

...

<filter name="myFilter" condition=":myFilterParam = MY_FILTERED_COLUMN">

</filter></class></pre>
...

Filter can also be attached to a collection:

Java Code:
<pre lang="java">
<set>

<filter name="myFilter" condition=":myFilterParam = MY_FILTERED_COLUMN">

</filter></set></pre>

Note: You may attach filter to class and collection at the same time.




The methods on Session are:

Java Code:
enableFilter(String filterName)
getEnabledFilter(String filterName)
disableFilter(String filterName)
Remember that the default behaviour is that filters are not enabled for a given session. You have to explicitly enabled them
through use of the Session.enabledFilter() method. It will return an instance of the Filter interface.

Using the simple filter defined above, it would look like:


Java Code:
session.enableFilter("myFilter").setParameter("myFilterParam", "some-value");
The methods on the org.hibernate.Filter interface do allow the method-chaining common to much of Hibernate.

This post presents an example which using temporal data with an effective record date pattern. Do go through the previous posts written on this topic.



Java Code:
<pre lang="java">
<filter-def name="effectiveDate">
<filter-param name="asOfDate" type="date">
</filter-param></filter-def>
<class name="Employee">
...
Java Code:
<many-to-one name="department" column="dept_id" class="Department">
<property name="effectiveStartDate" type="date" column="eff_start_dt"></property>
<property name="effectiveEndDate" type="date" column="eff_end_dt"></property>
...
<!--
Note that this assumes non-terminal records have an eff_end_dt set to
a max db date for simplicity-sake
-->
Java Code:
<filter name="effectiveDate">condition=":asOfDate BETWEEN eff_start_dt and eff_end_dt"/&gt;
</filter></many-to-one></class>
<class name="Department">
...
Java Code:
<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"/&gt;
</filter></one-to-many></key></set>
</class></pre>
Just to make sure that you get back currently effective records, enable the filter on the session prior to retrieving employee data.




Java Code:
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();

In the HQL snippet above, we only explicitly mentioned a salary constraint on the results, because of the enabled filter the query will return only currently active employees who have a salary greater than 1000000.

Remember that if you plan to using filters with outer joining be careful of the direction of the condition expression. It is safe to set this up for left outer joining, place the parameter first followed by the column name(s) after the operator.

After defining a filter, it might be attached to multiple entities and/or collections and each will have its own condition. Yes, it is tedious when the conditions are the same each time and you have to repeat the condition.




Use to define a default condition, either as an attribute or CDATA as shown below:

Java Code:
<filter-def name="myFilter" condition="abc &gt; xyz">...</filter-def>

<filter-def name="myOtherFilter">abc=xyz</filter-def></pre>
Now whenever you attach a filter to something without specifying a condition, this default condition will be used. You may overrides the default condition if you provide a specific condition as part of the attachment of the filter.

Submit "Hibernate Filters" to Facebook Submit "Hibernate Filters" to Digg Submit "Hibernate Filters" to del.icio.us Submit "Hibernate Filters" to StumbleUpon Submit "Hibernate Filters" to Google

Tags: None Add / Edit Tags
Categories
Hibernate , XML

Comments