Hibernate @PostLoad никогда не вызывается

Посмотрел многие форумы, но не нашел ответа... Простой материал, метод, аннотированный @PostLoad, никогда не вызывается... добавлен слушатель через @EntityListeners, но проблема остается. Я использую конфигурацию на основе SessionFactory.

5 ответов

Решение

EJB3 @PostLoad аннотация не работает при использовании SessionFactory на основе конфигурации, метод после загрузки никогда не будет вызван.

Либо использовать перехватчики Hibernate или события или EntityManager на основе конфигурации.

При использовании SessionFactory также существует альтернатива подходу перехватчиков или событий hibernate: реализация интерфейса жизненного цикла.

Вот как включить аннотации JPA после операции в Hibernate 5.

в Hibernate IntegratorServiceImpl использует java.util.ServiceLoader API, поэтому мы можем указать дополнительный список org.hibernate.integrator.spi.Integrator реализации мы хотим SessionFactory использовать.

Все, что нам нужно сделать, это указать поставщика услуг в META-INF/services/org.hibernate.integrator.spi.Integrator:

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

Вам также необходимо убедиться, что hibernate-entitymanager Баночка с соответствующей версией находится на вашем пути к классам.

our.custom.JpaAnnotationsIntegrator (взято из 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();
        }
    }
 }

Я также изо всех сил пытался заставить это работать на Hibernate4, используя фабрику сессий.

Я нашел решение довольно простым, но нигде не документированным с помощью Integrator (по-видимому, Hibernate4 работает с SessionFactory и слушателями). Проект hibernate-entitymanager предоставляет Integrator для добавления необходимых слушателей, чтобы связать аннотации EJB3 @PostLoad,... с фабрикой сеансов. Просто объявите класс JpaIntegrator как SPI.

Конкретно, просто добавьте файл с именем org.hibernate.integrator.spi.Integrator в папку META-INF/services и объявите в нем класс реализации (org.hibernate.ejb.event.JpaIntegrator).

Или включите прослушиватели событий Hibernate, которые обрабатывают обратные вызовы JPA. Это именно то, что делает HEM. Как это сделать, отличается в Hibernate 3 и Hibernate 4 (вы никогда не упоминали, какую версию вы используете); проверьте документацию для получения подробной информации о (а) вовлеченных слушателях событий и (б) как указать пользовательский набор слушателей.

Другие вопросы по тегам