I need to inject EntityManager in EntityListener class so that I can perform CRUD operation on it.
POJO:
@Entity
@EntityListner(AuditLogging.class)
c
Well, the first solution which came into my mind is a little "hack", but should work.
public class AuditInterceptor {
static setEntityManager emf;
@Autowired
public void setEntityManagerFactory(EntityManager emf) {
AuditInterceptor.emf = emf;
}
@PrePersist
public void prePersist(Object obj) {
EntityManager entityManager = emf.getEntityManager();
// Here I want to use ENTITY manager object so that I can perform CRUD operation
// with prePersist coming object.
entityManager.unwrap(Session.class).save(obj);
// But I am getting NULL POINTER EXCEPTION for entity manager object
}
}
Inside of your code use EntityManager entityManager = emf.getEntityManager()
Declare your AuditInterceptor
as a spring bean (@Component
with component-scan or define AuditorInterceptor
as a bean)
Anyways, I got this done by getting entityManager reference from EntityManagerFactory
bean which is configured in my jdbc-config.xml
. But again this is not what I wanted. I wanted to work around with @PersistenceContext
.
@Autowired
EntityManagerFactory entityManagerFactory;
private static EntityManager entityManager;
public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
entityManager=entityManagerFactory.createEntityManager();
this.entityManagerFactory = entityManagerFactory;
}
Here are few notes that we need to keep in mind:
EntityManager
into an EntityListener
(through
@PersistenceContext
). EntityListener
is not managed by any of the
containers@PersistenceContext
class cannot be static. So we cant
attain the instance while class loading. EntityManager
I used a ThreadLocal to pass the Spring Application Context which contains EntityManager around. Though I am not sure if it is safe Is it safe to pass in the Spring Application Context into a ThreadLocal associated with a request? but so far it is working for me.
I have faced a similar problem where I was trying to create history records for an entity using EntityListeners.
In order to resolve this problem, I have created utility class BeanUtil
with a static method to get the bean and used this util class to get bean inside my Entitylistener class
@Service
public class BeanUtil implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static <T> T getBean(Class<T> beanClass) {
return context.getBean(beanClass);
}
}
Now we can call BeanUtil.getBean() to get the bean of any type
public class FileEntityListener {
@PrePersist
public void prePersist(File target) {
perform(target, INSERTED);
}
@Transactional(MANDATORY)
private void perform(File target, Action action) {
EntityManager entityManager = BeanUtil.getBean(EntityManager.class);
entityManager.persist(new FileHistory(target, action));
}
}
We can use this BeanUtil
class to get any spring managed bean from anywhere, To know more you can read my article JPA Auditing: Persisting Audit Logs Automatically using EntityListeners.