What is Interceptors in Hibernate?

In the previous article, we have seen the CRUD Example in Hibernate. In this article, we will cover what is Interceptors in Hibernate with a simple example.

Interceptors as the name suggest are like a function in Java that is invoked every time by the framework BEFORE and AFTER an action invocation.

What are Interceptors in Hibernate?

Interceptors in Hibernate are used to record the changes in an entity’s property value BEFORE or AFTER they are read and write into a database.

  • It is basically used to perform operations such as logging.
  • Interceptors are used to perform Auditing.

How to use Hibernate Interceptors?

In order to use Hibernate Interceptors, we have to use the following steps.

  • Register the Interceptors.
  • Create the Hibernate Interceptors.

Register the Interceptors

In Hibernate, there are two ways to register the Interceptors.

Session-scoped: In this Interceptors are related to the session. Lets’ see the code on how to register using the session.

Session session = HibernateUtil.getSessionFactory()
  .withOptions()
  .interceptor(new MyInterceptor())
  .openSession();

SessionFactory-scoped: In this Interceptors are related to SessionFactory. Lets’ see the code on how to register using the SessionFactory.

SessionFactory sessionFactory = metadata.getSessionFactoryBuilder()
  .applyInterceptor(new MyInterceptor())
  .build();

Create Hibernate Interceptors

There are two ways to Implement Hibernate Interceptors:

  • One can use the above both ways to create Hibernate. But, it is recommended to extend the org. hibernate.EmptyInterceptor class because there are overall 14 methods which the Interceptor provides. So, if we Implement the Interceptor Interface it forces us to override all the methods.
  • So instead of we have another class EmptyInterceptor, we need to extend this class and override the method that we want.

Let’s see the methods of Interceptor Interface provide

  • onSave(): This method returns a boolean value and is called before an object is saved. 
  • onLoad(): This method returns a boolean value and is called just before an object is initialized.
  • onDelete(): This method is called before an object is deleted. 
  • preFlush(): This method is called before an object is flush.
  • postFlush(): This method is called after an object is flush.
  • instantiate(): This method is called when a class is instantiated.
  • findDirty(): This method gets called when the flush() method is called on Session Object.
  • onFlushDirty(): This method returns the boolean value and is called when the object of an entity is changed during a flush.
  • isUnsaved(): This method gets called when the object of the entity is passed to the saveOrUpdate() method.

Example of How to use  Hibernate Interceptors?

In this example, we will learn How to use Interceptor in Hibernate.

Let us first create a configuration file hibernate.cfg.xml file. 

  • When we want to create a table Just write create like this- <property name=”hbm2ddl. auto”>create</property> and then replace it with update(otherwise it will give an error).
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/college</property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password">khan</property>
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="hibernate.jdbc.batch_size">50</property>
    <property name="hibernate.show_sql">true</property>
    <property name="format_sql">true</property>
    <property name="hibernate.hbm2ddl.auto">update</property>
    <property name="cache.use_second_level_cache">true</property>
    <property name="cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>


    <mapping class="com.Hibernate_Interceptors.Student" />




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

Now Create a java Class Student for setting and getting data. We are creating annotated-based classes so we won’t need a mapping file now. (for annotation you can see the previous article How to use Annotation in Hibernate?)

Student.java

In this class Just write the @Entity and @Table followed by table name.

package com.Hibernate_Interceptors;

import javax.persistence.Cacheable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;



@Entity // specifies that class in an entity
@Table(name = "student") // defines the table
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public class Student {

  @Id // indicate it is a primary key of the table.
  @GeneratedValue(strategy = GenerationType.IDENTITY) // annotation is to
                            // configure the way of
                            // increment of the
                            // specified
                            // column(field).
  @Column(name = "id")
  private int id;

  @Column(name = "name")
  private String nameOfStudent;

  @Column(name = "address")
  private String add;

  @Column(name = "collegename")
  private String cn;

  public int getId() {
    return id;
  }

  public void setId(int id) {
    this.id = id;
  }

  public String getNameOfStudent() {
    return nameOfStudent;
  }

  public void setNameOfStudent(String nameOfStudent) {
    this.nameOfStudent = nameOfStudent;
  }

  public String getAdd() {
    return add;
  }

  public void setAdd(String add) {
    this.add = add;
  }

  public String getCn() {
    return cn;
  }

  public void setCn(String cn) {
    this.cn = cn;
  }

  public Student() {
    super();
  }

  @Override
  public String toString() {
    return "Student [id=" + id + ", nameOfStudent=" + nameOfStudent + ", add=" + add + ", cn=" + cn + "]";
  }
}

Create Helper class (HibernateUtil.java)to keep the Session Object.

package com.Hibernate_Interceptors;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {

  private static final SessionFactory sessionFactory = buildSessionFactory();
   
    private static SessionFactory buildSessionFactory() {
        try {
            // Create the SessionFactory from hibernate.cfg.xml
            return new Configuration().configure().buildSessionFactory();
        } catch (Throwable ex) {
            // Make sure you log the exception to track it
            System.err.println("SessionFactory failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }
 
    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
   
    public static void shutdown() {
        // Optional but can be used to Close caches and connection pools
        getSessionFactory().close();
    }
}

Create an Interceptor class(Interceptors.java) that extends EmptyInterceptors

package com.Hibernate_Interceptors;

import java.io.Serializable;

import org.hibernate.EmptyInterceptor;
import org.hibernate.type.Type;

public class Interceptors extends EmptyInterceptor {

  @Override
  public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
    // TODO Auto-generated method stub
    if(entity instanceof Student){
      Student student = (Student) entity;
      System.out.println("Student object gets created");
      return true;
    }
    return false;
  }
}

Here, we override the onSave() method of the EmptyInterceptors class to see whether the method is called when the object is saved. 

Now Create a Main class Test.java

package com.Hibernate_Interceptors;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

/**
 * Hello world!
 *
 */
public class Test 
{
    public static void main( String[] args )
    {
    	Session session = HibernateUtil.getSessionFactory().withOptions().interceptor(new Interceptors()).openSession();
    	
    	Transaction tx = null;
    	tx = session.beginTransaction();
    	System.out.println("***************Student Save...********************");
    	//Save an Object
    	Student student = new Student();
    	student.setNameOfStudent("Mr A");
    	student.setAdd("A B Street");
    	student.setCn("St. Aloysius");
    	session.save(student);
    	tx.commit();
    	session.close();
    	System.out.println("***************Student Saved *********************");
    }
}
  • on line no: 16, we have used Session-scoped interceptors.
  • on line no: 22 – 25, the object of an entity class is created and we have set the properties value using setter methods.
  • on line no:26, the student object is persisted using the session object. So, when this object is persisted onSave() method of Interceptor class will be called.

Output

***************Student Save...********************
Student object gets created
Hibernate: 
    insert 
    into
        student
        (address, collegename, name) 
    values
        (?, ?, ?)
***************Student Saved *********************

Thus, we can check here whenever the save() method is called onSave() method of Interceptors will be invoked.

Thus, in this article, we understood Interceptors in Hibernate, how to use it with a simple example.