Hibernate Event Interceptor

Its quite common when you create an application, there is a need to create an audit trail on the application level where all entity insert, update and delete events are logged.

In this post, I would like to describe a simple approach that can help you to avoid littering with unnecessary statements in your application code. The solution is to register a class as a listener on Hibernate events. Once class is triggered, you will be able to write audit information to a database or log file.

The following shows a Hibernate event interceptor class that is triggered when persistent entity is inserted, deleted or updated.

public class HibernateEventInterceptor	implements	PostInsertEventListener,
							PostUpdateEventListener,
							PostDeleteEventListener,
							Initializable {

	public HibernateEventInterceptor() {

	}

	public void initialize(Configuration cfg) {

	}

	public void onPostInsert(PostInsertEvent event) {
		String entityName = event.getPersister().getEntityName();
		System.out.println("Inserted entity: " + entityName);
	}

	public void onPostUpdate(PostUpdateEvent event) {
		String entityName = event.getPersister().getEntityName();
		System.out.println("Updated entity: " + entityName);
	}

	public void onPostDelete(PostDeleteEvent event) {
		String entityName = event.getPersister().getEntityName();
		System.out.println("Deleted entity: " + entityName);
	}
}

The following shows extra configuration that must be added to persistence.xml, in order for the interceptor class to be triggered:

<persistence>
	<persistence-unit name="org.example.demo">
	<jta-data-source>java:/test</jta-data-source>
		<properties>
			.
			.
			.
		<property name="hibernate.ejb.event.post-insert" value="org.example.demo.HibernateEventInterceptor"/>
		<property name="hibernate.ejb.event.post-update" value="org.example.demo.HibernateEventInterceptor"/>
		<property name="hibernate.ejb.event.post-delete" value="org.example.demo.HibernateEventInterceptor"/>
		</properties>
	</persistence-unit>
</persistence>

Hibernate – How To Map Two Collections of The Same Type in The Same Entity

Recently during development, I encountered a situation where I had to map two collections in the same entity, having collections and the entity it self of the same type.

I had persistent entity – Rule. Rule could have children rules: “action” rules and “else” rules. Children rules were also of type Rule.

Basically it was a one-to-many relationship mapping of an entity to itself twice:
Entity Rule could have two different collections of the same object type – Rule. The collections represented “action” and “else” rules.

The challenge that I faced was during XML generation of the persisted entity Rule:

I could successfully persist entity Rule with its children Rules to DB. But, when I was generating the XML, Hibernate was not able to differentiate between “action” and “else” rules and was adding every child Rule to each collection. This was causing the same entity to appear once in each collection:

<?xml version="1.0" encoding="UTF-8"?>
<Rule id="1">
	<ruleType>-1</ruleType>
	<actionChildren>
		<rule>1</rule>
		<rule>2</rule>
	</actionChildren>
	<elseChildren>
		<rule>1</rule>
		<rule>2</rule>
	</elseChildren>
</Rule>

I needed to “tell” somehow to Hibernate which child entity Rule should be added to which collection. I am not sure if my solution is the best in this case, but I created a discriminator property inside entity Rule – “ruleType”.

Respectively, in HBM file, in the mappings of one-to-many relationships, I specified by using SQL query, which rules should be added to the collection when XML is generated. The SQL query was inside where attribute of <list> element.

It done the trick for me – when I was adding a child rule to a parent entity, I was specifying child rule type. Therefore, Hibernate was generating XML correctly by adding “action” rules and “else” rules to their respective collections.

Here is entity Rule:

package org.example.rules;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public class Rule implements
			Serializable {

private static final long
	serialVersionUID = -76784L;

private int idx;
private int ruleType = -1;
private Rule parentRule = null;

private List<Rule> actionChildren =
		new ArrayList<Rule>();

private List<Rule> elseChildren =
		new ArrayList<Rule>();

/**
 * Default constructor
 */
public Rule() {

}

/**
 * @return the 'action' children
 */
public List<Rule> getActionChildren() {
	return actionChildren;
}

/**
 * @param children
 *            'action' children to set
 */
public void setActionChildren(List<Rule> actionChildren) {
	this.actionChildren = actionChildren;
}

/**
 * @return the 'else' children
 */
public List<Rule> getElseChildren() {
	return elseChildren;
}

/**
 * @param children
 *            'else' children to set
 */
public void setElseChildren(List<Rule> elseChildren) {
	this.elseChildren = elseChildren;
}

/**
 * Adds an 'action' child to the current rule
 *
 * @param actionChild
 *            The rule to be added as a child
 */

public void addActionChild(Rule actionChild) {
	if (!this.actionChildren.contains(actionChild)) {
		actionChild.setParentRule(this);
		this.actionChildren.add(actionChild);
	}
}

/**
 * Adds an 'else' child to the current rule
 *
 * @param elseChild
 *            The rule to be added as a child
 */

public void addElseChild(Rule elseChild) {
	if (!this.elseChildren.contains(elseChild)) {
		elseChild.setParentRule(this);
		this.elseChildren.add(elseChild);
	}
}

/**
 * @return the ruleType
 */
public int getRuleType() {
	return ruleType;
}

/**
 * @param ruleType
 *            the ruleType to set
 */
public void setRuleType(int ruleType) {
	this.ruleType = ruleType;
}

/**
 * @return collection index
 */
public int getIdx() {
	return idx;
}

/**
 * Sets collection index
 * @param collection index
 */
public int setIdx(int idx) {
	this.idx = idx;
}

/**
 * @return parent rule of the current rule
 */
public Rule getParentRule() {
	return parentRule;
}

/**
 * @param ruleParent
 *            the ruleParent to set
 */
public void setParentRule(Rule parentRule) {
	this.parentRule = parentRule;
}
}

Rule HBM file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<class name="org.example.rules.Rule"
	table="org_example_rules_Rule" node="Rule">

<id name="id" column="id" node="@id"
			unsaved-value="0">
	<generator class="native" />
</id>

<!--
Used to help Hibernate to discriminate
between children rules
-->
<property name="ruleType" column="ruleType"
								node="ruleType" />
<!--
Attribute 'where' holds SQL query used to help Hibernate
to discriminate between children rules of type 'action'
and children rules of type 'else'.

Since two children rule lists in the current HBM are of
the same type (org.example.rules.Rule), Hibernate needs
a 'hint' how to discriminate which rules belong to
which list when XML is generated.

If ruleType equals to '1', it means that the child
rule is 'action' rule.

If ruleType equals to '2', it means that the child
rule is 'else' rule.
-->
<list name="actionChildren" embed-xml="true"
		where="ruleType=1" cascade="all">

	<key column="parentrule_id" />
	<list-index column="idx" base="0" />
	<one-to-many class="org.example.rules.Rule"
		node="rule" embed-xml="false" />
</list>

<!--
If ruleType equals to '2', it means that the child
rule is 'else' rule.
-->
<list name="elseChildren" embed-xml="true"
		where="ruleType=2" cascade="all">

	<key column="parentrule_id" />
	<list-index column="idx" base="0" />
	<one-to-many class="org.example.rules.Rule"
		node="rule" embed-xml="false" />

</list>

<!--
Read-only index column, represents position of
the element in the list
-->
<property name="idx" column="idx" node="idx"
		update="false" insert="false" type="int" />

<!--
Embed XML must be equals to 'false',
otherwise when XML is generated for
children rules, parent XML will be
generated recursively
-->
<many-to-one name="parentRule" node="parentRule"
	column="parentrule_id" class="org.example.rules.Rule"
	not-null="false" insert="false" update="false"
	embed-xml="false" />

</class>
</hibernate-mapping>

Generally, I would not advise to design persistent entities in this way, it can create problem later on. For example if there is a need to delete child entities. It can become a bit tricky, since entity has relationship to it self.

Suggestions? Flames?

Bitwise Operation In Hibernate 3

Hi all…
i encountered a small problem in doing bitwise operations with hibernate. Until now, HIbernate 2 HQL parser has supported bitwise operations. Hibernate 3 for some reason does not support it. So if you want to work around it, you have to create a custom SQLfunction and add it to the dialect, that will map the bitwise operator.

You have to create your own class, which will extend from StandardSQLFunction class and will implement SQLFunction interface. You have to override render() method from the interface mentioned before and provide your own implementation.

In my example I am showing how to use ampersand symbol (‘&’) for bitwise operation.

Important note:
Hibernate team people have changed SQLFunction interface when upgrading from version 3.0.2 to 3.0.3, so your custom implementation of bitwise operation in version 3.0.2 will not work in 3.0.3. So keep that in mind.

Update (13.Jan.2010):
According to one of the blog reader’s this example has successfully worked under Hibernate v.3.2.6!

Implementation:
I am using Sysbase dialect, so i will create a class that extends this dialect with my own implementation:

package com.project.test.dialect;

import org.hibernate.Hibernate;

public class SybaseDialect extends 
	org.hibernate.dialect.SybaseDialect{
	 
	public SybaseDialect() {
	   super();
	   registerFunction("bitwise_and", 
		new BitwiseAndFunction("bitwise_and", 
				Hibernate.INTEGER));
	} 

}

What it means basically that i am registering a function by the name of bitwise_and the return type will be of type Integer.

Now, my custom class for SQLFunction like this:

package com.project.test.dialect;

import java.util.List;

import org.hibernate.QueryException;
import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.type.Type;

public class BitwiseAndFunction
		extends StandardSQLFunction
			 implements SQLFunction {

 public BitwiseAndFunction(String name) {
		super(name);
 }

 public BitwiseAndFunction(String name, Type type) {
	super(name, type);
 }

 public String render(List args,
	SessionFactoryImplementor factory)
			throws QueryException {
   if (args.size() != 2) {
      throw new IllegalArgumentException(
	"the function must be passed 2 arguments");
   }
   StringBuffer buffer = new
	StringBuffer(args.get(0).toString());
   buffer.append(" & ").append(args.get(1));
   return buffer.toString();
 }
}

The method render() accepts two arguments, if less – exception will be thrown. Once arguments are passed to the method, it will return a String that will look something like this (assuming that the passed arguments were one (1) and two (2)):

1 & 2

In my project, I am using named queries in my hbm.xml files, so below you can see a part of my hbm.xml file where I use my bitwise function:

<query name="UserPermissionsForEnttiy">
select object(ep) from EntityPermission ep where ep.userid =
:userid and ep.entityid = :entityid and ep.classname =
:classname and bitwise_and(ep.permission,:requiredpermission) > 0 
</query>

Note the two arguments that i am passing to the bitwise_and function.

Also not forget to update your persistence XML with your custom dialect class, this is how my persistence.xml looks like:

<persistence>
<persistence-unit name="com.project.test.users">
<jta-data-source>java:/DefaultDS</jta-data-source>
   <properties>
   <property name="hibernate.dialect" 
	value="com.project.test.dialect.SybaseDialect"/>
   <property name="hibernate.hbm2ddl.auto" 
	value="update"/>
   <property name="hibernate.show_sql" 
	value="true"/>
	   .
	   .
	   .
   </properties>
</persistence-unit>
</persistence>

Please note the hibernate.dialect property. As a value i gave the canonical name of my custom SysbaseDialect class.

Once you finished implementing your custom dialect classes, you can JAR them and put into the lib directory of your JBoss instance where the rest of your Hibernate libraries are.

Do not forget to restart your JBoss – it needs to load your newly added JAR, for you to be able to use it ;)