我需要在EntityListener类中注入EntityManager,以便我可以对它执行CRUD操作。
POJO:
@Entity
@EntityListner(AuditLogging.class)
class User
{
//Getter / setter of properties
}
AuditLogging(Listner类)
public class AuditInterceptor
{
@PersistenceContext
EntityManager entityManager;
public void setEntityManager(EntityManager entityManager)
{
this.entityManager = entityManager;
}
@PrePersist
public void prePersist(Object obj)
{
// 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
}
}
JDBC-CONFIG.XML
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter" />
<property name="packagesToScan" value="com.XXXXX.entity" />
<property name="jpaProperties">
</bean>
<!-- Datasource -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="${jdbc.driver.classname}" />
<property name="jdbcUrl" value="${jdbc.url}" />
</bean>
<!-- transaction Manager -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
EntityListener不受任何容器管理.EntityListeners由JPA实例化,因此Spring没有机会注入EntityManager。 我的问题是,我们如何在EntityListener类中注入EntityManager以便我可以对它执行CRUD操作???
答案 0 :(得分:5)
我遇到了类似的问题,我试图使用EntityListeners为实体创建历史记录。
为了解决这个问题,我创建了一个带有静态方法的实用程序类BeanUtil
来获取bean并使用这个util类来获取我的Entitylistener类中的bean
@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);
}
}
现在我们可以调用BeanUtil.getBean()来获取任何类型的bean
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));
}
}
我们可以使用此BeanUtil
类从任何地方获取任何Spring托管bean。要了解更多信息,您可以阅读我的文章JPA Auditing: Persisting Audit Logs Automatically using EntityListeners。
答案 1 :(得分:3)
无论如何,我通过从我的jdbc-config.xml中配置的EntityManagerFactory bean获取entityManager引用来完成此操作。但这又不是我想要的。我想解决@PersistenceContext。
@Autowired
EntityManagerFactory entityManagerFactory;
private static EntityManager entityManager;
public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory)
{
entityManager=entityManagerFactory.createEntityManager();
this.entityManagerFactory = entityManagerFactory;
}
以下是我们需要记住的一些注意事项:
1. We can't inject an EntityManager into an EntityListener(through @presistenceContext). EntityListener
is not managed by any of the containers
2. @presistenceContext class cannot be static. So we cant attain the instance while class loading.
3. EntityListeners are instantiated by JPA, so Spring does not have an opportunity to inject EntityManager
答案 2 :(得分:0)
嗯,我想到的第一个解决方案是“hack”,但是应该可行。
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
}
在代码内部使用EntityManager entityManager = emf.getEntityManager()
将AuditInterceptor解析为spring bean。 (@Component with component-scan或将AuditorInterceptor定义为bean。)
答案 3 :(得分:0)
我使用ThreadLocal传递了包含EntityManager的Spring Application Context。尽管我不确定Is it safe to pass in the Spring Application Context into a ThreadLocal associated with a request?是否安全,但到目前为止它对我还是有用的。