2013-10-07 2 views
6

Я использую JPA-2.0 с Hibernate в моем уровне доступа к данным.Ввод объекта Entity Manager в Hibernate's EmptyInterceptor

Для целей ведения журнала аудита, я использую EmptyInterceptor Hibernate путем настройки ниже собственности в persistence.xml:

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

Где AuditLogInterceptor распространяется в Hibernate "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 
    } 
} 

Я использую диспетчер объектов JPA на уровне доступа к данным для выполнения операций с базой данных. конфигурация JPA, как показано ниже:

<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> 

Мои 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);  
    } 

} 

Я хотел бы, чтобы ввести JPA менеджер сущностей в «AuditLogInterceptor», так что я могу выполнять операции с базами данных в «AuditLogInterceptor», как мой абстрактная DAO.

Любая идея? Каким должно быть правильное решение?

ответ

7

У меня есть простой способ для выполнения операции с базой данных с помощью JPA Entity менеджера в «AuditLogInterceptor»

я создал ниже класс, который даст ссылку контекста приложения:

@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; 
     } 
    } 

Создан класс доступа данных :

@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); 
    } 
} 

И использовали 'ApplicationContextProvider' в 'AuditLogInterceptor', чтобы получить ссылку на 'MyAuditDAO', который оказывает JPA ENTI ty manager как свойство, которое вводится во время инициализации DAO. Теперь с помощью «MyAuditDAO» я могу выполнять операции с базой данных.

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

Как насчет безопасности потоков? –

+0

Я пытаюсь сделать это в JPA2, чтобы получить ссылку на мой auditLogRepository, поскольку использование аннотации @Resource ничего не вводило и оставило меня с NPE. – Stephane

0

Я рассматриваю persistenceManager, успешно инициированный в вашем классе Аннотация. Вы можете иметь класс AuditLogDAO, который расширяет ваш AbstractDao. Внесите класс AuditLogDAO в ваш перехватчик и вызовите auditLogDAO.save(entity); и другими способами.

Или напишите класс Util, который выполняет операции DB и вводит класс util в ваш перехватчик.

 Смежные вопросы

  • Нет связанных вопросов^_^