4.0 changes the way event listeners get registered to leverage some added capabilities, namely services and integrators. I won't get into services too much as they are covered elsewhere. But lets start with the notion of an Integrator.
Integrator contract
Specifically, we are talking about the org.hibernate.integrator.spi.Integrator
interface. The idea behind an org.hibernate.integrator.spi.Integrator
is to provide a simple means to allow developers to hook into the process of building a functioning SessionFactory
. A standard service provided by Hibernate is the ability to discover org.hibernate.integrator.spi.Integrator
implementations by utilizing the Java java.util.ServiceLoader
mechanism. Developers simply define a file named /META-INF/services/org.hibernate.integrator.spi.Integrator
and make it available on the classpath. Essentially, the content of this file is one or more fully-qualified org.hibernate.integrator.spi.Integrator
implementation class names, one per line each. Please see the java.util.ServiceLoader
JavaDocs for the complete spec of the allowed syntax of content in this file.
The org.hibernate.integrator.spi.Integrator
interface defines 2 methods of interest:
public interface Integrator { /** * Perform integration. * * @param configuration The configuration used to create the session factory * @param sessionFactory The session factory being created * @param serviceRegistry The session factory's service registry */ public void integrate(Configuration configuration, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry); /** * Tongue-in-cheek name for a shutdown callback. * * @param sessionFactory The session factory being closed. * @param serviceRegistry That session factory's service registry */ public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry); /** * Ignore this form! Just do nothing in impl. It uses the new metamodel api slated for completion in 5.0 */ public void integrate(MetadataImplementor metadata, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry ); }
The method integrate
allows us to hook into the building process; disintegrate
allows us to hook into a SessionFactory
shutting down.
Registration
Hibernate itself has a few implementations of the org.hibernate.integrator.spi.Integrator
interface that perform event listener registration that might be good to look at for reference.
- https://github.com/hibernate/hibernate-orm/blob/master/hibernate-envers/src/main/java/org/hibernate/envers/event/EnversIntegrator.java
- https://github.com/hibernate/hibernate-orm/blob/master/hibernate-entitymanager/src/main/java/org/hibernate/ejb/event/JpaIntegrator.java
The general process for registering listeners is as follows
public void integrate(Configuration configuration, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { // As you might expect, an EventListenerRegistry is the place with which event listeners are registered It is a service // so we look it up using the service registry final EventListenerRegistry eventListenerRegistry = serviceRegistry.getService( EventListenerRegistry.class ); // If you wish to have custom determination and handling of "duplicate" listeners, you would have to add an implementation // of the org.hibernate.event.service.spi.DuplicationStrategy contract like this eventListenerRegistry.addDuplicationStrategy( myDuplicationStrategy ); // EventListenerRegistry defines 3 ways to register listeners: // 1) This form overrides any existing registrations with eventListenerRegistry.setListeners( EventType.AUTO_FLUSH, myCompleteSetOfListeners ); // 2) This form adds the specified listener(s) to the beginning of the listener chain eventListenerRegistry.prependListeners( EventType.AUTO_FLUSH, myListenersToBeCalledFirst ); // 3) This form adds the specified listener(s) to the end of the listener chain eventListenerRegistry.appendListeners( EventType.AUTO_FLUSH, myListenersToBeCalledLast ); }