Create database triggers like features using Hibernate events

When you are creating a Java application with database operations, it is obvious to use JDBC as the database communication method. Well, that’s not the case here. Imagine a situation like this, if you are developing an application that manages an inventory and when a product reaches to its re-order level, your application should automatically populate and send a purchase order to the supplier.

Here you’ll say that “Ok, I can do it by creating a trigger in the database”. But the thing is how that trigger notifies or talks to your application about the product?

Currently there is no support for triggers in JDBC (This is clearly my opinion. I Googled about this for a day and I found nothing. Guys, you can check this out if you are interested). But I must acknowledge to the changes in the database in real time through my Java application.

What are the database events that can be monitored by your application?

Following are the usual CRUD (Create, Read, Update, and Delete) events that occur in any regular database.

  1. Pre – Select:  These types of events occur before executing any select statement against the database.
  2. Post – Select: These types of events occur after executing any select statement against the database.
  3. Pre – Insert: These types of events occur before you execute any insert statement.
  4. Post – Insert: These types of events occur after executing an insert statement.
  5. Pre – Update: These types of events occur before executing any update statements against the database.
  6. Post – Update: These types of events occur after executing any update statement against the database.
  7. Pre – Delete: These types of events occur before executing any delete statement against the database.
  8. Post – Delete: These types of events occur after executing a any delete statement against the database.

Apart from that, there can be several types of events occur in a database. But for the sake of simplicity, I’ll not consider them because they are not in our scope.

How to trap those events in  your Java application?

There are several ways to do that. But we already know using JDBC is impossible at the moment. One way to achieve this is implementing a thread in your application to monitor the changes in the database object (such as a table in the database). If any change occurred, that thread can dispatch the changes in your application. But this is not a good practice. What if your database has more than ten tables? Then you have to create ten threads for each table and that would be a great mess regarding to the performance. So you have to omit that approach.

But Hibernate (An open source ORM framework) can save your day by using Its Interceptors and event system to trap those events.

Let’s see how can we do it using hibernate.

Hibernate Event System

Before I proceed, I assume that you have some knowledge about Hibernate and its general architecture. (Visit www.hibernate.org for more information).

Hibernate ships with powerful event system. You can browse the org.hibernate.event package for more information, but this package was poorly documented.

You can react to particular events in the persistence layer using this event architecture. Essentially all of the methods of the Session interface correlate to an event. You have a LoadEvent, aFlushEvent, etc (consult the XML configuration-file DTD or the org.hibernate.event package for the full list of defined event types). When a request is made of one of these methods, the Hibernate Session generates an appropriate event and passes it to the configured event listeners for that type. Out-of-the-box, these listeners implement the same processing in which those methods always resulted. However, you are free to implement a customization of one of the listener interfaces (i.e., the LoadEvent is processed by the registered implementation of the LoadEventListener interface), in which case their implementation would be responsible for processing any load() requests made of the Session.

A custom listener should implement the appropriate interface for the event it wants to process. There are several types of event listener interfaces. If you want to receive change notifications, all you have to do is implement the appropriate event interface in your program. For example, for pre-select events, you have to implement the LoadEventListener. For post-update events, you have to implement the PostUpdateListener interface.

Below is the commonly used listener interfaces in hibernate.

Event Listeners

Event Listeners in org.hibernate.event package

Along with these listeners, you can use associated event objects to get information related with a particular event. For instance, after updating an object you can retrieve the updated instance of an object using PostUpdateEvent object.  Then it can be used to set the properties like update timestamp.

Below is the commonly used event objects associated with event listeners.

Event Objects

Event Objects in org.hibernate.event package

How to use hibernate events in your application?

  1. Implement the appropriate event interface in your application.
  2. Register the listeners in hibernate.cfg.xml file.

Very simple application to demonstrate the post-update event type

Here I’m going to create an application to trap an object after updating.

package com.dunithd.events;

import org.hibernate.event.PostUpdateEvent;
import org.hibernate.event.PostUpdateEventListener;

import com.dunithd.events.InventoryProduct;

/**
 * A class that implements PostUpdateEventListener interface
 *
 * @author duischen
 * @version 1.0, Oct 27, 2009
 */
public class ProductUpdateListener implements PostUpdateEventListener {

	@Override
	public void onPostUpdate(PostUpdateEvent event) {
		if (event.getEntity() instanceof InventoryProduct) {
			InventoryProduct product = (InventoryProduct) event.getEntity();

			// Check for quantity and re-order level for this product
			int quantity = product.getQuantity();
			int reOrderLevel = product.getReOrderLevel();

			// Check if this product is under the re-order level
			if (quantity <= reOrderLevel) {
				System.out.println("Need to purchase.");
			} else {
				System.out.println("No Need to purchase.");
			}

		}
	}

}

Then register this listener in hibernate.cfg.xml file.

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
	<session-factory>
		.....
	<mapping resource="com/dunithd/events/InventoryProduct.hbm.xml" />

	  <!-- Register the listeners -->
	  <listener type="post-update"/>

	</session-factory>
</hibernate-configuration>

Create the database table as follows.

create table products (
	int product_id primary key,
	varchar(100) description,
	float price,
	int quantity,
	int reorder_level
)

When you run your application, you can see the message “Need to purchase.” or “No need to purchase”, depending on the quantity of the product.

About these ads

9 thoughts on “Create database triggers like features using Hibernate events

  1. True, but the hibernate events can only monitor db changes made from within the hibernate session, right ? So if some other application changes your tables, the event will not be fired – am I correct ?

    • Yes, you are correct.
      If you need to monitor the changes, you always have to initialize a session and wait for changes to be occurred.
      You can use a daemon thread to watch for changes…

    • also…these hibernate event listeners are going to be much, much slower than an actual DB trigger – incur additional introspection, method calls, and most importantly additional DB queries. Real DB triggers are designed to minimize performance impact.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s