2010-05-10 5 views
18

많은 포럼을 보았지만 대답을 찾지 못했다. @PostLoad로 주석 된 메소드는 결코 호출되지 않는다. @EntityListeners를 통해 리스너가 추가되었지만 문제가 남아있다. SessionFactory 기반 구성을 사용하고 있습니다.Hibernate @PostLoad는 결코 호출되지 않는다.

답변

15

SessionFactory 기반 구성을 사용할 때 EJB3 @PostLoad 주석이 작동하지 않으면 사후로드 방법이 호출되지 않습니다.

최대 절전 모드의 Interceptors or events 또는 EntityManager 기반 구성을 사용하십시오.

+2

콜백 절대적으로 작업 할 수 있습니다. 적절한 Hibernate 이벤트 리스너를 사용 가능하게 설정하기 만하면된다. –

+0

다음은 이벤트 리스너를 활성화하는 방법입니다. https://n1njahacks.wordpress.com/2016/10/07/jpa-callbacks-with-hibernates-sessionfactory-and-nityentagerager/ –

9

SessionFactory : Lifecycle 인터페이스를 구현할 때 hibernate의 인터셉터 또는 이벤트 접근 방식에 대한 대안도 있습니다.

+3

하지만이 버그에주의하십시오. https : //hibernate.onjira.co.kr/browse/HHH-6043 또한 Lifecycle.onLoad (컬렉션이 초기화되기 전에 호출 됨 - Hibernate 4.1.8에서 수정 될 때까지 호출 됨) – Jakub

1

JPA 콜백을 처리하는 Hibernate 이벤트 리스너를 활성화합니다. 바로 HEM이하는 일입니다. 이것이 어떻게되는지 Hibernate 3와 Hibernate 4는 다르다. (a) 관련 이벤트 리스너 및 (b) 사용자 정의 리스너 세트 지정 방법에 대한 문서를 확인하십시오.

+0

어쩌면 나는 두껍습니다. 그러나 어떻게해야 할 지 찾아내는 데 어려움을 겪고 있습니다. Hibernate 4에 대한 문서에서 이것을하십시오. – David

2

세션 팩토리를 사용하여 Hibernate4에서이 작업을하기 위해 애써 왔습니다.

솔루션은 매우 단순하지만 Integrator (어디 까지나 SessionFactory 및 리스너를 다루는 Hibernate4의 방법)를 사용하여 어디에도 문서화되지 않았습니다. hibernate-entitymanager 프로젝트는 EJB3의 어노테이션 @PostLoad, ...을 세션 팩토리에 링크하기 위해 필요한 리스너를 추가하기 위해 Integrator를 제공한다. 클래스 을 JpaIntegratorSPI 길로 선언하십시오.

구체적으로는, 단지 META-INF/서비스 폴더에 org.hibernate.integrator.spi.Integrator라는 이름의 파일을 추가하고 (그 안에 org.hibernate.ejb.event.JpaIntegrator을 구현 클래스를 선언)

+0

좋은 해결책입니다. 참고로, Hibernate 4.3.5에서, 파일의 내용은 "org.hibernate.jpa.event.spi.JpaIntegrator"이어야한다. –

+0

이것은 Hibernate 5에서 flush cascades를 깨뜨리는 것으로 나타 났지만, 나는 함께 갔다. 해결 방법은 아래 나의 대답을 보라. –

+0

@Matt 나는 아주 오래된 질문을 알고 있지만이 META-INF/Services는 어디에서 찾아야합니까? 나는 절전 모드를 다운로드하고 변경 한 후에 만 ​​폴더에서 찾을 수 있습니다. 여전히 작동하지 않습니다. –

3

여기에 5

Hibernate의 IntegratorServiceImpljava.util.ServiceLoader API를 사용하여 최대 절전 모드에서 JPA의 포스트 연산 주석을 수 있도록, 그래서 우리는 우리가을 원하는 org.hibernate.integrator.spi.Integrator 구현의 추가 목록을 지정할 수있는 방법3210을 사용하십시오.

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

또한 적절한 버전의 'hibernate-entitymanager'항아리 클래스 경로에 있는지 확인해야합니다

우리가해야 할 일은 META-INF/services/org.hibernate.integrator.spi.Integrator에서 서비스 공급자를 지정합니다. (org.hibernate.jpa.event.spi.JpaIntegrator에서 촬영)

our.custom.JpaAnnotationsIntegrator는 : SessionFactory를 사용하는 경우

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(); 
     } 
    } 
} 
관련 문제