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.
Join the DZone community and get the full member experience.
Join For FreeHibernate 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 <filter-def> 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 <filter-param> 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.
<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping package="data"> <class name="Flight" table="hibernate_filter_demo.flight_db"> <id name="id" type = "int" column="id"> <generator class = "increment"/> </id> <property name="flightNo" type="string" length="10" column="flight_No"/> <property name="source" type="string" length="15" column="source"/> <property name="destination" type="string" length="15" column="destination"/> <property name="status" type="string" length="20" column="status"/> <filter name="statusFilter" condition=":statusParam=status"/> </class> <filter-def name="statusFilter"> <filter-param name="statusParam" type="string"/> </filter-def></hibernate-mapping>
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 <filter> XML element to each class or collection. The <filter> 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 <filter> XML element must correspond to a <filter-def> 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
Java Persistence with Hibernate an excellent book on Hibernate
Opinions expressed by DZone contributors are their own.
Comments