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 (вы никогда не упоминали, какую версию вы используете); проверьте документацию для получения подробной информации о (а) вовлеченных слушателях событий и (б) как указать пользовательский набор слушателей.