Events

As discussed in Chapter 1, Entity and Session, almost every action in the persistence context is translated into an event. This includes events such as load, save, merge, lock, and flush. For a complete list of events in Hibernate, you should look at the JavaDoc for org.hibernate.event.spi.EventType.

Every event in Hibernate has a corresponding listener that acts when the event is fired. The Hibernate event architecture uses the Service Provider Interface model to discover event listeners. This allows you to plug in your own listener for a certain event. In this section, we will show you how to write event listeners.

Event listener

Hibernate defines the event contract using the listener interfaces (refer to org.hibernate.event.spi) and it provides a default implementation for each event (see org.hibernate.event.internal). Through the service provider interface, you can append additional listeners. Keep in mind that event listeners are considered singletons, so they are not thread-safe. So, if you implement your own listener, ensure that it doesn't maintain any state.

Hibernate discovers new event listeners through another service contract called integrator. This is done because registering event listeners must occur when the session factory is created. If you have used older versions of Hibernate, such as version 3 or older, you may know that you needed to modify the session factory tag in the Hibernate configuration file and add your custom event listener in the event tag.

Another important note is that Hibernate gives you the flexibility to append or prepend to the existing (default) listeners or override the internal listeners. This distinction is critical. In some cases, the default listener doesn't perform any action, so you can safely override them. But, in other cases, you should always append or prepend your custom listener unless you want to override the default behavior.

Registering listeners

As mentioned earlier, all event listener operations are defined using the internal contracts defined by Hibernate interfaces in org.hibernate.event.spi. If you wish to write your own event listener, you will need to implement one of these interfaces. The following code shows the implementation of two event listeners:

public class MyPreLoadEventListener implements PreLoadEventListener {
  @Override
  public void onPreLoad(PreLoadEvent event) {
    System.out.println("**** About to load entity with ID:" 
                          + event.getId());
  }
}

public class MyPostLoadEventListener implements PostLoadEventListener {
  @Override
  public void onPostLoad(PostLoadEvent event) {
    Object entity = event.getEntity();
    System.out.println("**** Just loaded entity with ID:" 
                          + event.getId());
    System.out.println(entity);
  }
}

The first one is called when an entity is about to be loaded, and the second one is called after an entity has been loaded into the persistence context.

Once your listener classes are implemented, you need to create your own integrator that implements org.hibernate.integrator.spi.Integrator and is used to register these listeners. Here is an example:

public class LoadIntegrator implements Integrator {
  public void integrate(Configuration configuration,
    SessionFactoryImplementor sessionFactory,
    SessionFactoryServiceRegistry serviceRegistry) {
    final EventListenerRegistry listenerRegistry = 
      serviceRegistry.getService(EventListenerRegistry.class);

    listenerRegistry.appendListeners(EventType.PRE_LOAD, 
       new MyPreLoadEventListener());
    listenerRegistry.appendListeners(EventType.POST_LOAD, 
       new MyPostLoadEventListener());
  }

  @Override
  public void integrate(MetadataImplementor metadata,
      SessionFactoryImplementor sessionFactory,
      SessionFactoryServiceRegistry serviceRegistry) {
  }

  @Override
  public void disintegrate(SessionFactoryImplementor sessionFactory,
    SessionFactoryServiceRegistry serviceRegistry) {
  }
}

Note that the event listener registry is obtained from the session factory service registry; furthermore, the new listeners are appended to the existing listeners already registered for each event type.

Finally, for your custom integrator to be discovered, you need to add the integrator class name to a file located in your class path with the name META-INF/services/org.hibernate.integrator.spi.Integrator:

Registering listeners

In this case, the content of the INF/services/org.hibernate.integrator.spi.Integrator file will simply be a list of all the integrators that you wish to be discovered at runtime, for example: com.you.package.integrator.LoadIntegrator.

In the next section, we will show you how to achieve a similar functionality using interceptors.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.14.98