I am using JPA-2.0 with Hibernate in my data access layer.
For audit logging purposes, I am using Hibernate's EmptyInterceptor by configuring below property in persistence.xml:
<property name="hibernate.ejb.interceptor"
value="com.mycom.audit.AuditLogInterceptor" />
Where AuditLogInterceptor extends hibernate's '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
}
}
I am using JPA entity manager in data access layer to perform database operations. JPA configuration is like below:
<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>
My AbstractDAO is :
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);
}
}
I would like to inject JPA entity manager in 'AuditLogInterceptor' so that I can perform database operations in 'AuditLogInterceptor' like my abstract DAO.
Any Idea? What should be the proper solution?
You can use the @PersistenceContext annotation to inject an EntityManager in an EJB 3.0 client (such as a stateful or stateless session bean, message-driven bean, or servlet).
We can get the EntityManager by creating a custom repository that extends, for instance, a built-in JpaRepository. We don't have direct access to the EntityManager in a JpaRepository. Therefore, we need to create our own.
The EntityManager is an API that manages the lifecycle of entity instances. An EntityManager object manages a set of entities that are defined by a persistence unit. Each EntityManager instance is associated with a persistence context.
Attempting to close an EntityManagerFactory while one or more of its EntityManager s has an active transaction may result in an IllegalStateException . Closing an EntityManagerFactory should not be taken lightly.
I have got a simple way to perform database operation using JPA Entity Manager in 'AuditLogInterceptor'
I have created below class that will give the application context reference:
@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;
}
}
Created Data access class:
@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);
}
}
And used 'ApplicationContextProvider' in 'AuditLogInterceptor' to get the reference of 'MyAuditDAO' that is having JPA entity manager as a property which is injected during DAO initialization. Now with the help of 'MyAuditDAO' I can perform database operations.
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);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With