在 Hibernate 的 EmptyInterceptor 中注入 JPA 的实体管理器
Posted
技术标签:
【中文标题】在 Hibernate 的 EmptyInterceptor 中注入 JPA 的实体管理器【英文标题】:Injecting JPA's Entity Manager in Hibernate's EmptyInterceptor 【发布时间】:2013-10-13 14:45:55 【问题描述】:我在数据访问层中使用 JPA-2.0 和 Hibernate。
出于审计日志记录的目的,我通过在 persistence.xml 中配置以下属性来使用 Hibernate 的 EmptyInterceptor:
<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);
我想在“AuditLogInterceptor”中注入 JPA 实体管理器,以便像抽象 DAO 一样在“AuditLogInterceptor”中执行数据库操作。
有什么想法吗?正确的解决方案应该是什么?
【问题讨论】:
【参考方案1】:我有一种简单的方法可以在“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”来获取“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);
【讨论】:
我正在尝试在 JPA2 中执行此操作以获取对我的 auditLogRepository 的引用,因为使用 @Resource 注释没有注入任何内容,并给我留下了 NPE。【参考方案2】:我正在考虑在您的 Abstract 类中成功启动 persistenceManager
。你可能有一个类AuditLogDAO
,它扩展了你的AbstractDao
。将 AuditLogDAO 类注入你的拦截器并调用auditLogDAO.save(entity);
和其他方法。
或者编写一个 Util
类来执行数据库操作并将 util 类注入你的拦截器。
【讨论】:
以上是关于在 Hibernate 的 EmptyInterceptor 中注入 JPA 的实体管理器的主要内容,如果未能解决你的问题,请参考以下文章
关于hibernate的saveOrUpdate方法的一个问题
在hibernate5中,关于让hibernate自动创建表报错的问题。