2010-05-10 5 views
18

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

ответ

15

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

Используйте либо конфигурацию Interceptors or events Hibernate, либо конфигурацию на основе EntityManager.

+2

Обратные вызовы могут абсолютно работать при использовании SessionFactory. Вам просто нужно включить соответствующих слушателей событий Hibernate. –

+0

Вот как включить прослушиватели событий: https://n1njahacks.wordpress.com/2016/10/07/jpa-callbacks-with-hibernates-sessionfactory-and-no-entitymanager/ –

9

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

+3

Но будьте осторожны с этой ошибкой: https: //hibernate.onjira.com/browse/HHH-6043, который также выполняется для Lifecycle.onLoad (вызывается перед инициализацией коллекций - до тех пор, пока он не был исправлен в Hibernate 4.1.8) – Jakub

1

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

+0

Возможно, я толстый, но мне трудно найти, как сделайте это в документации для Hibernate 4. – David

2

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

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

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

+0

Хорошее решение. FYI, начиная с Hibernate 4.3.5, содержимое файла должно быть «org.hibernate.jpa.event.spi.JpaIntegrator». –

+0

Это решение, с которым я пошел, хотя я обнаружил, что он сломает флеш-каскады в Hibernate 5. См. Мой ответ ниже для исправления. –

+0

@Matt Я знаю его очень старый вопрос, но где я должен найти этот META-INF/Services? я могу найти его только в папке, где я загружал hibernate и после внесения изменений, он все равно не работает. –

3

Вот как включить после оп аннотациями 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(); 
     } 
    } 
} 
Смежные вопросы