Внедрение Entity Manager JPA в EmptyInterceptor Hibernate

Я использую JPA-2.0 с Hibernate на уровне доступа к данным.

Для целей ведения журнала аудита я использую 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.

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


person Narendra Verma    schedule 07.10.2013    source источник


Ответы (2)


У меня есть простой способ выполнить операцию с базой данных с помощью JPA Entity Manager в «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 в качестве свойства, которое вводится во время инициализации 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);

    }  
} 
person Narendra Verma    schedule 10.10.2013
comment
Я пытаюсь сделать это в JPA2, чтобы получить ссылку на мой auditLogRepository, поскольку использование аннотации @Resource ничего не вводило и оставило меня с NPE. - person Stephane; 09.04.2015

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

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

person CHowdappaM    schedule 07.10.2013