Hibernate @PostLoad never gets invoked

前端 未结 5 1697
情话喂你
情话喂你 2020-12-03 14:02

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.

相关标签:
5条回答
  • 2020-12-03 14:20

    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.

    0 讨论(0)
  • 2020-12-03 14:25

    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();
            }
        }
     }
    
    0 讨论(0)
  • 2020-12-03 14:31

    I've also been struggling to make this work on Hibernate4, using the session factory.

    I found the solution quite simple but not documented anywhere using Integrator (Apparently the Hibernate4's way to deal with SessionFactory and listeners). The hibernate-entitymanager project provides an Integrator to add the required listeners to link EJB3's annotations @PostLoad, ... to the session factory. Just declare the class JpaIntegrator the SPI way.

    Concretely, just add a file named org.hibernate.integrator.spi.Integrator in the META-INF/services folder and declare the implementation class in it (org.hibernate.ejb.event.JpaIntegrator)

    0 讨论(0)
  • 2020-12-03 14:31

    Or enable the Hibernate event listeners that handle JPA callbacks. That is exactly what HEM does. How that is done is different between Hibernate 3 and Hibernate 4 (you never mentioned which version you are using); check the documentation for details on (a) the event listeners involved and (b) how to specify custom set of listeners.

    0 讨论(0)
  • 2020-12-03 14:38

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

    0 讨论(0)
提交回复
热议问题