2013-10-07 14 views
6

Sto usando JPA-2.0 con Hibernate nel mio livello di accesso ai dati.Iniezione di Entity Manager di JPA in EmptyInterceptor di Hibernate

Ai fini della registrazione di controllo, io sto usando EmptyInterceptor di Hibernate configurando sotto proprietà in persistence.xml:

<property name="hibernate.ejb.interceptor" 
       value="com.mycom.audit.AuditLogInterceptor" /> 

Dove AuditLogInterceptor estende ibernazione del 'org.hibernate.EmptyInterceptor'.

public class AuditLogInterceptor extends EmptyInterceptor { 

    private Long userId; 

    public AuditLogInterceptor() {} 

    @Override 
    public boolean onSave(Object entity, Serializable id, Object[] state, 
      String[] propertyNames, Type[] types) throws CallbackException { 
     // Need to perform database operations using JPA entity manager 
     return false; 
    } 

    @Override 
    public boolean onFlushDirty(Object entity, Serializable id, 
      Object[] currentState, Object[] previousState, 
      String[] propertyNames, Type[] types) { 
     // other code here   
     return false; 
    } 

    @Override 
    public void postFlush(Iterator iterator) throws CallbackException { 
     System.out.println("I am on postFlush"); 
     // other code here 
    } 
} 

Sto utilizzando gestore di entità JPA nel livello di accesso ai dati per eseguire operazioni di database. configurazione JPA è come qui di seguito:

<bean id="entityManagerFactory" 
     class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" 
     p:persistenceUnitName="PersistenceUnit" 
     p:persistenceXmlLocation="classpath*:persistence.xml" 
     p:dataSource-ref="dataSource" p:jpaVendorAdapter-ref="jpaAdapter"> 
     <property name="loadTimeWeaver"> 
      <bean 
       class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" /> 
     </property> 
    </bean> 

mio AbstractDAO è:

public class AbstractDao<T, ID extends Serializable> { 

    private final transient Class<T> persistentClass; 

    protected transient EntityManager entityManager; 

    @SuppressWarnings("unchecked") 
    public AbstractDao() { 

     this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; 
    } 

    @PersistenceContext 
    public final void setEntityManager(final EntityManager entityMgrToSet) { 

     this.entityManager = entityMgrToSet; 
    } 

    public final Class<T> getPersistentClass() { 

     return persistentClass; 
    } 

    public final void persist(final T entity) { 

     entityManager.persist(entity);  
    } 

} 

Vorrei iniettare JPA entity manager in 'AuditLogInterceptor' in modo che possa eseguire operazioni di database in 'AuditLogInterceptor' come il mio DAO astratto.

Qualche idea? Quale dovrebbe essere la soluzione corretta?

risposta

7

ho un modo semplice per eseguire l'operazione di database che utilizza JPA Entity Manager 'AuditLogInterceptor'

ho creato sotto classe che darà il riferimento contesto di applicazione:

@Component("applicationContextProvider") 
    public class ApplicationContextProvider implements ApplicationContextAware { 
     private static ApplicationContext context; 

     public static ApplicationContext getApplicationContext() { 
      return context; 
     } 

     @Override 
     public void setApplicationContext(ApplicationContext ctx) { 
      context = ctx; 
     } 
    } 

Creato classe di accesso dati :

@Repository("myAuditDAO") 
public class myAuditDAO<T, ID extends Serializable> { 

    private final transient Class<T> persistentClass; 

    protected transient EntityManager entityManager; 

    @SuppressWarnings("unchecked") 
    public MyDAO() { 

     this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; 
    } 

    @PersistenceContext 
    public final void setEntityManager(final EntityManager entityMgrToSet) { 

     this.entityManager = entityMgrToSet; 
    } 

    public final Class<T> getPersistentClass() { 

     return persistentClass; 
    } 

    public final T findById(final ID theId) { 

     return entityManager.find(persistentClass, theId); 
    } 

    public final void persist(final T entity) { 

     entityManager.persist(entity); 
    } 

    public final void merge(final T entity) { 

     entityManager.merge(entity); 
    } 
} 

E usato 'ApplicationContextProvider' in 'AuditLogInterceptor' per ottenere il riferimento del 'MyAuditDAO' che sta avendo JPA Enti ty manager come una proprietà che viene iniettata durante l'inizializzazione DAO. Ora con l'aiuto di "MyAuditDAO" posso eseguire operazioni di database.

public class AuditLogInterceptor extends EmptyInterceptor { 

    @Override 
    public void postFlush(Iterator iterator) throws CallbackException { 

     // Here we can get the MyAuditDao reference and can perform persiste/merge options 
     MyAuditDao myAuditDao = (MyAuditDao) ApplicationContextProvider.getApplicationContext().getBean("myAuditDao"); 

     // myAuditDao.persist(myEntity); 

    } 
} 
+0

E la sicurezza del filo? –

+0

Sto provando a farlo in JPA2 per ottenere un riferimento al mio auditLogRepository in quanto l'annotazione @Resource non ha iniettato nulla e mi ha lasciato con un NPE. – Stephane

0

Sto considerando persistenceManager avviato correttamente nella classe Abstract. Potresti avere una classe AuditLogDAO che estende il tuo AbstractDao. Iniettare la classe AuditLogDAO nell'intercettore e chiamare auditLogDAO.save(entity); e altri metodi.

Oppure scrivere una classe Util che esegue operazioni DB e inserisce la classe util sull'intercettore.

Problemi correlati