Hibernate Interceptors with Example

In Hibernate, interceptors are used to inspect the changes in entity’s property values before they are written and after they are read from a database.

You can use the Hibernate interceptor to perform the various operations such as logging, auditing, profiling etc.

1. Registering Interceptors

In Hibernate, an interceptor can either be Session-scoped or SessionFactory-scoped.

1. Session-scoped interceptors are used when a Session is opened. The following code snippet shows how to add an interceptor to a Session.

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

2. SessionFactory-scoped or global interceptors are used when SessionFactory is configured and these interceptors will be applied to applied to all Session opened from that SessionFactory. The following code snippet shows how to add an interceptor to a SessionFactory.

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

2. How to Create Hibernate Interceptors?

There are two ways of defining interceptors:

1. implementing the org.hibernate.Interceptor interface
2. extending the org.hibernate.EmptyInterceptor class 

There are around 14 callback methods which the interceptor provides for us to override and use.

Some of them are onLoad, onDelete, onSave, onFlushDirty, findDirty, etc

If you are creating your interceptor implementing the Interceptor interface then you may need to override all the methods provided.

Instead of implementing this interface directly, it is usually better to extend EmptyInterceptor and override only the callback methods of interest.

3. Example Hibernate Interceptor

1. Create Interceptor Class

By extending EmptyInterceptor Class

import com.pt.entities.Employee;
import org.hibernate.EmptyInterceptor;
import org.hibernate.type.Type;
import java.io.Serializable;

public class MyLogInterceptor extends EmptyInterceptor {

    public boolean onSave(Object entity, Serializable id, Object[] state,
                          String[] propertyNames, Type[] types) {
        if (entity instanceof Employee) {
            Employee emp = (Employee) entity;
            System.out.println(emp.toString());
        }
        return super.onSave(entity, id, state, propertyNames, types);
    }
}

2. Employee Entity looks like this

Create your own set of Entity class like this.

@Entity
@Table(name = "Employee")
@NamedQueries({
        @NamedQuery(name = "Employee.findAll", query = "from Employee emp"),
        @NamedQuery(name = "Employee.findByName",
                query = "from Employee emp where emp.firstName=:firstName"),
})
public class Employee implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private int id;

    @Column(name = "first_name")
    private String firstName;

    @Column(name = "last_name")
    private String lastName;

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

// getters & setters & toString()
// ...
}

3. Create HibernateUtility Class – to create session a session factory

Below is the code of HibernateUtility Class – in this we are creating a sessionfactory and registering our Employee Enitity class.

package com.pt.standalone;

import com.pt.entities.Employee;
import org.hibernate.SessionFactory;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Environment;

import java.util.HashMap;
import java.util.Map;

public class HibernateUtility {

    private static StandardServiceRegistry registry;
    private static SessionFactory sessionFactory;

    public static SessionFactory getSessionFactory() {
        if (sessionFactory == null) {
            try {

                // Create registry builder
                StandardServiceRegistryBuilder registryBuilder = new StandardServiceRegistryBuilder();

                // Hibernate settings equivalent to hibernate.cfg.xml's properties
                Map<String, String> settings = new HashMap<>();
                settings.put(Environment.DRIVER, "com.mysql.cj.jdbc.Driver");
                settings.put(Environment.URL, "jdbc:mysql://localhost:3306/testdb");
                settings.put(Environment.USER, "root");
                settings.put(Environment.PASS, "root");
                settings.put(Environment.DIALECT, "org.hibernate.dialect.MySQL57Dialect");

                // Apply settings
                registryBuilder.applySettings(settings);

                // Create registry
                registry = registryBuilder.build();

                // Create MetadataSources
                MetadataSources sources = new MetadataSources(registry).addAnnotatedClass(Employee.class);

                // Create Metadata
                Metadata metadata = sources.getMetadataBuilder().build();

                // Create SessionFactory

                sessionFactory = metadata.getSessionFactoryBuilder().build();
            } catch (Exception e) {
                e.printStackTrace();
                if (registry != null) {
                    StandardServiceRegistryBuilder.destroy(registry);
                }
            }
        }
        return sessionFactory;
    }

    public static void shutdown() {
        if (registry != null) {
            StandardServiceRegistryBuilder.destroy(registry);
        }
    }
}

4. Run – main method Class

Now run the main class.

import com.pt.entities.Employee;
import org.hibernate.Session;

public class TestHB {

    public static void main(String[] args) {

        Session session = HibernateUtility.getSessionFactory().withOptions().
                interceptor(new MyLogInterceptor()).openSession();
        session.beginTransaction();
        
        System.out.println("Save Employee...");

        // saving an object
        Employee emp = new Employee(10,"mak","robins","NA");
        session.save(emp);
  }
}

5. Output

Save Employee...
Employee{id=10, firstName='mak', lastName='robins', address='NA'}

Summary

In this article, we learnt about Hibernate Interceptors, how to create hibernate interceptors, its various uses and a working example.
I hope you liked it !