복붙노트

[SPRING] EntityListeners에 EntityManager를 삽입하는 방법

SPRING

EntityListeners에 EntityManager를 삽입하는 방법

EntityListener 클래스에 EntityManager를 삽입하여 CRUD 작업을 수행 할 수 있도록해야합니다.

POJO :

@Entity
@EntityListner(AuditLogging.class)
class User
{
      //Getter / setter of properties
}

감사 로깅 (Listener 클래스)

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는 컨테이너에 의해 관리되지 않습니다 .EntityListener는 JPA에 의해 인스턴스화되므로 Spring에는 EntityManager를 삽입 할 수있는 기회가 없습니다. 내 질문은 EntityListener 클래스에 EntityManager를 삽입하여 어떻게 CRUD 작업을 수행 할 수 있습니까?

해결법

  1. ==============================

    1.EntityListeners를 사용하여 엔티티에 대한 히스토리 레코드를 작성하려고하는 것과 비슷한 문제점에 직면했습니다.

    EntityListeners를 사용하여 엔티티에 대한 히스토리 레코드를 작성하려고하는 것과 비슷한 문제점에 직면했습니다.

    이 문제를 해결하기 위해 Bean을 가져 오기위한 정적 메소드 BeanUtil을 생성하고이 util 클래스를 사용하여 Bean을 EntityListener 클래스 내부에서 가져 왔습니다.

    @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 클래스를 사용하여 어디서나 스프링 관리 빈을 얻을 수 있습니다. 더 많은 정보를 얻으려면 JPA 감사 : EntityListeners를 사용하여 자동으로 감사 로그 유지하기.

  2. ==============================

    2.어쨌든이 작업은 jdbc-config.xml에 구성된 EntityManagerFactory bean에서 entityManager 참조를 가져와 수행합니다. 그러나 이것은 내가 원한 것이 아닙니다. @PersistenceContext로 해결하고 싶었습니다.

    어쨌든이 작업은 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
    
  3. ==============================

    3.글쎄, 내 마음에 들어온 첫 번째 해결책은 약간 "해킹"이지만 작동해야한다.

    글쎄, 내 마음에 들어온 첫 번째 해결책은 약간 "해킹"이지만 작동해야한다.

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

    감사 인터셉터를 스프링 빈으로 선언하십시오. (@Component with component-scan 또는 감사 자 인터셉터를 bean으로 정의하십시오.)

  4. from https://stackoverflow.com/questions/22171221/how-to-inject-entitymanager-in-entitylisteners by cc-by-sa and MIT license