Java 如何在EntityListeners中注入EntityManager

Java 如何在EntityListeners中注入EntityManager,java,spring,hibernate,spring-mvc,spring-data-jpa,Java,Spring,Hibernate,Spring Mvc,Spring Data Jpa,我需要在EntityListener类中注入EntityManager,以便对其执行CRUD操作 POJO: AuditLogging(Listner类) } JDBC-CONFIg.xml <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataS

我需要在EntityListener类中注入EntityManager,以便对其执行CRUD操作

POJO:

AuditLogging(Listner类)

}

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不由任何容器管理。EntityListener由JPA实例化,因此Spring没有机会注入EntityManager。
我的问题是,我们如何在EntityListener类中注入EntityManager,以便我可以对其执行CRUD操作?

好吧,我想到的第一个解决方案是有点“黑客”,但应该可以工作

    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()


将您的
auditioninterceptor
声明为Springbean(
@Component
使用组件扫描或将
auditioninterceptor
定义为bean)

无论如何,我是通过从
EntityManagerFactory
bean获取entityManager引用来实现的,该bean是在我的
jdbc config.xml
中配置的。但这又不是我想要的。我想处理
@PersistenceContext

  @Autowired
  EntityManagerFactory entityManagerFactory;

  private static EntityManager entityManager;

  public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
    entityManager=entityManagerFactory.createEntityManager();
    this.entityManagerFactory = entityManagerFactory;
  }
以下是我们需要记住的几个注意事项:

  • 我们无法将
    EntityManager
    注入
    EntityListener
    (通过
    @PersistenceContext
    )<代码>EntityListener不由任何 容器
  • @PersistenceContext
    类不能是静态的。所以我们不能 在类加载时获取实例
  • EntityListeners是 由JPA实例化,因此Spring没有机会 注入
    EntityManager

  • 我曾经遇到过一个类似的问题,我试图使用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
    类从任何地方获取任何spring管理的bean,您可以阅读我的文章了解更多信息。

    我使用ThreadLocal来传递包含EntityManager的spring应用程序上下文。虽然我不确定它是否安全,但到目前为止它对我有效。

    @PersistenceContext不能成为静态的。我的示例不再使用@PersistenceContext。谷歌也让我想到了这一点
      @Autowired
      EntityManagerFactory entityManagerFactory;
    
      private static EntityManager entityManager;
    
      public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
        entityManager=entityManagerFactory.createEntityManager();
        this.entityManagerFactory = entityManagerFactory;
      }
    
    @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);
        }
    
    }
    
    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));
        }
    
    }