Monday, July 5, 2010

Introduction to Hibernate Filters

Hibernate
is one of the most popular ORM solutions being used in the
Java persistence world. In this article we will learn how to use Hibernate
filters. A sample application is also provided for the better understanding.

With
Hibernate3 there is a new way to filtering the results of searches.
Sometimes it is required to only process a subset of the data in the
underlying Database tables. Hibernate filters are very useful in
those situations. Other approaches for these kind of problems is to
use a database view or use a WHERE clause in the query or Hibernate
Criteria API.

But
Hibernate filters can be enabled or disabled during a Hibernate
session. Filters can be parameterized also. This way one can manage
the ‘visibility’ rules within the Integration tier. They can be used
in the scenarios where you need to provide the capability of security
roles, entitlements or personalization.

When to use
Hibernate Filters

Let’s
take an example, consider a web application that does the reporting
for various flights. In future course there is a change in
requirement such that flights are to be shown as per their status (on
time, delayed or cancelled).

This
can also be done using a WHERE clause within the SQL SELECT
query or Hibernate’s HQL SELECT query. For a small application it is
okay to do this, but for a large and complex application it might be
a troublesome effort. Moreover it will be like searching each and
every SQL query and making the changes in the existing code which
have been thoroughly tested.

This
can also be done using Hibernate’s Criteria API but that also means
changing the code at numerous places that is all working fine.
Moreover in both the approaches, one need to be very careful so that
they are not changing existing working SQL queries in inadvertent
way.

Filters
can be used like database views, but parameterized inside the
application. This way they are useful when developers have very
little control over DB operations. Here I am going to show you the
usage of Hibernate filters to solve this problem. When the end users
select the status, your application activates the flight’s status for
the end user’s Hibernate session. Any SQL query will only return the
subset of flights with the user selected status. Flight status is
maintained at two locations- Hibernate Session and flight status
filter.

One
of the other use cases of filters I can think of is in the user’s view
of the organization data. A user can only view the data that he/she
is authorized to. For example an admin can see data for all the users in the organization, manager can see the data for all the employees reporting to him/her in his/her group while an employee can only see his/her data. If a user moves from one group to another-with a
very minimal change using Hibernate Filters this can be implemented.

Note:
This is a very simple application and un-necessary complexity has
been taken out to better understand the application of Hibernate
filters. Please feel free to add bells and whistles on your own to
this sample application.

How to use
Hibernate Filters

Hibernate
filters are defined in Hibernate mapping documents (hbm.xml file)-which
are easy to maintain. One can programmatically turn on or off the
filters in the application code. Though filters can’t be created at
run time, they can be parameterized which makes them quite flexible
in nature. We specify the filter on the column which is being used to
enable/disable visibility rules. Please go thru the example application in which the filter
is applied on flight status column and it must match a named
parameter. After that at run time we specify one of the possible
values.

Example Application

The
example application is a very elementary flight reporting system.
Some prior knowledge of Hibernate is required to understand it fully.

Please
refer to the code provided with this article. This can be imported as
project in Eclipse IDE. You need to download hibernate3.jar
under Hibernate Core. MySQL5 is used as the backend DB. MySQL driver
viz. mysql-connector-java-5.1.6-bin.jar
, Java
1.5
and Eclipse
IDE
needs to be downloaded from appropriate sources.

A
good amount of details in terms of working with Hibernate has been
abstracted into HibernateUtil.java so that users with very less
experience with Hibernate can also use the sample application. The file
‘hibernate.cfg.xml’ can be used as it is. This is the hibernate configuration file. This sample application is
ready to be executed provided you have MySQL DB already
installed. To make it run with other databases, you need to make the
changes in ‘hibernate.cfg.xml’ file. DDL is also provided as part of the Zip file.

Getting started
with the example

First
define filters in the Hibernate mapping documents, using the
XML element. These filter definitions must contain
the name of the filter and the names and types of any filter
parameters. Specify filter parameters with the
XML element. Filter parameters are similar to the named parameters
for HQL queries. We need to specify a’:'(colon) before the parameter
name/condition. Here is the mapping file from the sample code.

                                     

Note:
All the boilerplate hibernate mapping files can be created using the
Hibernate
tools.

Now
attach the filters to class or collection mapping elements. You can
attach a single filter to more than one class or collection. To do
this, you add a XML element to each class or
collection. The XML element has two attributes viz.
name and condition. The name references a filter definition (in the
sample application it’s : statusFilter) while condition is analogous
to a WHERE clause in HQL. Please go thru the complete hibernate
mapping file from the HibernateFilters.zip archive.

Note:
Each XML element must correspond to a
element. It is possible to have more than one filter for each filter
definition, and each class can have more than one filter. Idea is to
define all the filter parameters in one place and then refer them in
the individual filter conditions.

In
the java code, we can programmatically enable or disable the filter.
By default the Hibernate Session doesn’t have any filters enabled on
it.

The
Session interface contains the following methods:

  • public
    Filter enableFilter(String filterName)

  • public
    Filter getEnabledFilter(String filterName)

  • public
    void disableFilter(String filterName)

The
Filter interface contains some of the important methods:

  • public
    Filter setParameter(String name, Object value)

  • public
    Filter setParameterList(String name, Collection values)

  • public
    Filter setParameterList(String name, Object[] values)

setParameter()
method is mostly used. Be careful and specify only the type of java
object that you have mentioned in the parameter at the time of
defining filter in the mapping file.

The
two setParameterList() methods are useful for using IN clauses in
your filters. If you want to use BETWEEN clauses, use two different
filter parameters with different names.

Now
let’s see what we need to do in the java code.

At
the time of enabling the filter on session-use the name that you have
provided in the mapping file for the filter name for the
corresponding column in the table. Similarly condition name should
contain one of the possible values for that column. This condition is
being set on the filter.

public class HibernateFilterDemo{  public static void main(String argsp[])  {     SessionFactory factory = HibernateUtil.getSessionFactory();     Session session = factory.openSession();     insertData("DL6149", "RIC", "JFK", "ontime", session);     ....     Filter filter = session.enableFilter("statusFilter");     filter.setParameter("statusParam", "delayed");     showData(session);     ....     session.close();  }    public static void insertData(String flightNo, String source,                  String destination, String status, Session session)  {     session.beginTransaction();     ....     session.getTransaction().commit();  }    public static void showData(Session session)  {     session.beginTransaction();     Query query = session.createQuery("from Flight");     ....     session.getTransaction().commit();  }}

Please
go thru the source code provided with this article(HibernateFilters.zip). It contains the
DDL scripts for creating tables in MySQL, Java Code, Hibernate
mapping and configuration file and eclipse project settings.
The project can be directly imported into Eclipse IDE. The DDL can let you work with any other Database of your choice too. Please feel free to write to me in case of any issues in terms of executing this sample application.

Conclusion

Hibernate
filters is one of the alternatives to DB views, SQL where clause,
Hibernate Criteria API.It is a useful way to segregate database
concerns from the remaining application code. They help in reducing
the complexity of HQL or SQL queries. Filters can be enabled as and
when they are required. Enjoy working with Hibernate Filters!

Resources

  • Sample
    code for this
    article

  • Hibernate
    Filters

  • Java
    Persistence with Hibernate
    an excellent book on Hibernate

No comments:

Post a Comment