Посмотрел на многие форумы, но не нашел ответа... Простой материал, метод, аннотированный с помощью @PostLoad, никогда не вызывается... добавил слушателя через @EntityListeners, но проблема остается. Я использую конфигурацию на основе SessionFactory.
Hibernate @PostLoad никогда не вызывается
Ответ 1
Аннотация EJB3 @PostLoad
не работает при использовании конфигурации на основе SessionFactory
, метод post-load никогда не будет вызван.
Используйте Hibernate перехватчики или события или конфигурацию на основе EntityManager
.
Ответ 2
Существует также альтернатива спящим перехватчикам или событиям при использовании SessionFactory: реализация Lifecycle интерфейса.
Ответ 3
Здесь, как включить JPA post op annotations в Hibernate 5.
Спящий режим IntegratorServiceImpl
использует API java.util.ServiceLoader
, поэтому мы можем указать дополнительный список реализаций 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
" jar соответствующей версии находится в вашем пути к классам.
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();
}
}
}
Ответ 4
Я также пытаюсь сделать эту работу на Hibernate4, используя сеанс factory.
Я нашел решение довольно простым, но не документированным в любом месте с помощью Integrator (видимо, Hibernate4 способ иметь дело с SessionFactory и слушателями). Проект hibernate-entitymanager предоставляет Integrator для добавления необходимых слушателей для ссылки на аннотации EJB3 @PostLoad,... на сеанс factory. Просто объявите класс JpaIntegrator SPI.
Конкретно просто добавьте файл с именем org.hibernate.integrator.spi.Integrator в папку META-INF/services и объявите в нем класс реализации (org.hibernate.ejb.event. JpaIntegrator)
Ответ 5
Или включите прослушиватели событий Hibernate, которые обрабатывают обратные вызовы JPA. Это именно то, что делает HEM. Как это делается, отличается между Hibernate 3 и Hibernate 4 (вы никогда не упоминали, какую версию вы используете); проверьте документацию для получения подробной информации о (a) участвующих слушателях событий и (b) о том, как указать пользовательский набор слушателей.