2013-10-07 300 views
6

我在数据访问层使用的是JPA-2.0和Hibernate。在Hibernate的EmptyInterceptor中注入JPA的实体管理器

对于审计记录的目的,我使用Hibernate的EmptyInterceptor通过配置以下属性在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

我有在“AuditLogInterceptor”

使用JPA实体管理器执行数据库操作的简单方法我在下面类创建,这将使应用程序上下文参考:

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

和使用 'AuditLogInterceptor' ApplicationContextProvider“获得即具有JPA ENTI 'MyAuditDAO' 的参考ty管理器作为在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在您的Abstract类中成功启动。您可能有一个AuditLogDAO类,它扩展了您的AbstractDao。将AuditLogDAO类注入拦截器并调用auditLogDAO.save(entity);和其他方法。

或者编写一个Util类,它执行数据库操作并将util类注入到拦截器中。

相关问题