2010-05-10 15 views
18

Sahen in vielen Foren, aber keine Antwort gefunden ... Einfaches Zeug, Methode kommentiert mit @PostLoad nie aufgerufen wird ... hinzugefügt Hörer über @EntityListeners aber Problem bleibt. Ich verwende SessionFactory-basierte Konfiguration.Hibernate @PostLoad wird nie aufgerufen

Antwort

15

Die EJB3 @PostLoad Annotation funktioniert nicht, wenn eine SessionFactory basierte Konfiguration verwendet wird, die Post-Load-Methode wird nie aufgerufen.

Entweder verwenden Hibernate Interceptors or events oder eine EntityManager basierte Konfiguration.

+2

Die Rückrufe absolut funktionieren, wenn Session verwenden. Sie müssen lediglich die richtigen Hibernate-Ereignis-Listener selbst aktivieren. –

+0

So aktivieren Sie die Ereignis-Listener: https://n1njahacks.wordpress.com/2016/10/07/jpa-callbacks-with-hibernates-sessionfactory-and-no-entitymanager/ –

9

Es gibt auch eine Alternative zum Interceptor- oder Event-Ansatz von Hibernate, wenn SessionFactory verwendet wird: Implementierung der Schnittstelle Lifecycle.

+3

Aber Vorsicht vor diesem Fehler: https: //hibernate.onjira.com/browse/HHH-6043, das auch für Lifecycle.onLoad gilt (wird aufgerufen, bevor die Sammlungen initialisiert werden - bis es in Hibernate 4.1.8 behoben wurde) – Jakub

1

Oder aktivieren Sie die Hibernate-Ereignis-Listener, die JPA-Callbacks verarbeiten. Genau das macht HEM. Wie das gemacht wird unterscheidet sich zwischen Hibernate 3 und Hibernate 4 (Sie haben nie erwähnt, welche Version Sie verwenden); Weitere Informationen zu (a) den beteiligten Ereignis-Listenern und (b) zum Angeben eines benutzerdefinierten Listener-Sets finden Sie in der Dokumentation.

+0

Vielleicht bin ich dick, aber es fällt mir schwer zu finden Tun Sie dies in der Dokumentation für Hibernate 4. – David

2

Ich habe auch gekämpft, um diese Arbeit auf Hibernate4 zu machen, mit der Sitzungsfabrik.

Ich fand die Lösung ziemlich einfach, aber nirgendwo mit Integrator dokumentiert (Anscheinend die Art und Weise, wie Hibernate4 mit SessionFactory und Listenern umgehen). Das hibernate-entitymanager Projekt stellt einen Integrator zur Verfügung, um die erforderlichen Listener hinzuzufügen, um die EJB3-Annotationen @PostLoad, ... mit der Sitzungsfactory zu verknüpfen. Erklären Sie einfach die Klasse JpaIntegrator die SPI Weise.

Konkret, fügen Sie einfach eine Datei namens org.hibernate.integrator.spi.Integrator im META-INF/services Ordner und erklären die Implementierungsklasse in ihm (org.hibernate.ejb.event.JpaIntegrator)

+0

Schöne Lösung. FYI, ab Hibernate 4.3.5 sollte der Inhalt der Datei "org.hibernate.jpa.event.spi.JpaIntegrator" sein. –

+0

Dies ist die Lösung, mit der ich auch ging, obwohl ich festgestellt habe, dass es flutende Kaskaden in Hibernate 5 unterbrechen wird. Siehe meine Antwort unten für eine Lösung. –

+0

@Matt Ich weiß, es ist eine sehr alte Frage, aber wo soll ich diese META-INF/Services finden? Ich kann es nur in dem Ordner finden, wo ich Hibernate heruntergeladen habe und nachdem ich Änderungen vorgenommen habe, funktioniert es immer noch nicht. –

3

Hier ist, wie PPV-Post op Anmerkungen in den Ruhezustand aktivieren 5.

Hibernate IntegratorServiceImpl verwendet die java.util.ServiceLoader API, so können wir eine zusätzliche Liste von org.hibernate.integrator.spi.Integrator Implementierungen angeben möchten wir die SessionFactory zu verwenden.

Alles, was wir tun müssen, ist ein Service-Provider angeben, 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 

Sie auch benötigen, um sicherzustellen, dass ‚hibernate-entitymanager‚jar der entsprechenden Version auf Ihrem Classpath ist.

our.custom.JpaAnnotationsIntegrator (entnommen aus 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(); 
     } 
    } 
} 
Verwandte Themen