Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate @PostLoad never gets invoked

Looked at many forums but haven't found answer...Simple stuff, method annotated with @PostLoad never gets invoked...added listener via @EntityListeners but problem remains. I'm using SessionFactory based configuration.

like image 522
tropikalista Avatar asked May 10 '10 12:05

tropikalista


3 Answers

The EJB3 @PostLoad annotation doesn’t work when using a SessionFactory based configuration, the post-load method will never get called.

Either use Hibernate's Interceptors or events or an EntityManager based configuration.

like image 93
Pascal Thivent Avatar answered Oct 16 '22 05:10

Pascal Thivent


There is also an alternative to hibernate's interceptors or events approach when using SessionFactory: implementing Lifecycle interface.

like image 10
Vadzim Avatar answered Oct 16 '22 06:10

Vadzim


Here's how to enable JPA's post op annotations in Hibernate 5.

Hibernate’s IntegratorServiceImpl uses the java.util.ServiceLoader API, so we can specify an additional list of org.hibernate.integrator.spi.Integrator implementations we want the SessionFactory to use.

All we need to do is specify a service provider in META-INF/services/org.hibernate.integrator.spi.Integrator:

# This allows us to use JPA-style annotation on entities, such as @PostLoad
our.custom.JpaAnnotationsIntegrator

You will also need to ensure that ‘hibernate-entitymanager‘ jar of the appropriate version is on your classpath.

our.custom.JpaAnnotationsIntegrator (taken from org.hibernate.jpa.event.spi.JpaIntegrator):

package our.custom;

import org.hibernate.annotations.common.reflection.ReflectionManager;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.internal.MetadataImpl;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventType;
import org.hibernate.integrator.spi.Integrator;
import org.hibernate.jpa.event.internal.core.JpaPostDeleteEventListener;
import org.hibernate.jpa.event.internal.core.JpaPostInsertEventListener;
import org.hibernate.jpa.event.internal.core.JpaPostLoadEventListener;
import org.hibernate.jpa.event.internal.core.JpaPostUpdateEventListener;
import org.hibernate.jpa.event.internal.jpa.CallbackBuilderLegacyImpl;
import org.hibernate.jpa.event.internal.jpa.CallbackRegistryImpl;
import org.hibernate.jpa.event.spi.jpa.CallbackBuilder;
import org.hibernate.jpa.event.spi.jpa.ListenerFactory;
import org.hibernate.jpa.event.spi.jpa.ListenerFactoryBuilder;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.service.spi.SessionFactoryServiceRegistry;

/**
 * This integrator allows us to use JPA-style post op annotations on Hibernate entities.
 *

 * This integrator is loaded by <code>org.hibernate.integrator.internal.IntegratorServiceImpl</code> from
 * <code>META-INF/services/org.hibernate.integrator.spi.Integrator</code> file.
 *

 * <b>Note</b>: This code is lifted directly from <code>org.hibernate.jpa.event.spi.JpaIntegrator</code>
 *
 * @author Val Blant
 */
public class JpaAnnotationsIntegrator implements Integrator {
    private ListenerFactory jpaListenerFactory;
    private CallbackBuilder callbackBuilder;
    private CallbackRegistryImpl callbackRegistry;

    @Override
    public void integrate(Metadata metadata, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
        final EventListenerRegistry eventListenerRegistry = serviceRegistry.getService( EventListenerRegistry.class );

        this.callbackRegistry = new CallbackRegistryImpl();

        // post op listeners
        eventListenerRegistry.prependListeners( EventType.POST_DELETE, new JpaPostDeleteEventListener(callbackRegistry) );
        eventListenerRegistry.prependListeners( EventType.POST_INSERT, new JpaPostInsertEventListener(callbackRegistry) );
        eventListenerRegistry.prependListeners( EventType.POST_LOAD, new JpaPostLoadEventListener(callbackRegistry) );
        eventListenerRegistry.prependListeners( EventType.POST_UPDATE, new JpaPostUpdateEventListener(callbackRegistry) );

        // handle JPA "entity listener classes"...
        final ReflectionManager reflectionManager = ( (MetadataImpl) metadata )
                .getMetadataBuildingOptions()
                .getReflectionManager();

        this.jpaListenerFactory = ListenerFactoryBuilder.buildListenerFactory( sessionFactory.getSessionFactoryOptions() );
        this.callbackBuilder = new CallbackBuilderLegacyImpl( jpaListenerFactory, reflectionManager );
        for ( PersistentClass persistentClass : metadata.getEntityBindings() ) {
            if ( persistentClass.getClassName() == null ) {
                // we can have non java class persisted by hibernate
                continue;
            }
            callbackBuilder.buildCallbacksForEntity( persistentClass.getClassName(), callbackRegistry );
        }
    }

    @Override
    public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
        if ( callbackRegistry != null ) {
            callbackRegistry.release();
        }
        if ( callbackBuilder != null ) {
            callbackBuilder.release();
        }
        if ( jpaListenerFactory != null ) {
            jpaListenerFactory.release();
        }
    }
 }
like image 4
Val Blant Avatar answered Oct 16 '22 07:10

Val Blant