Hibernate PostUpdateEventListener вызывается для каждого вызова Jpa - PullRequest
1 голос
/ 09 апреля 2019

Я использую Spring Data JPA с ядром hibernate 5.3.7. Я написал собственный слушатель, который реализует PostUpdateEventListener. Моё требование - вызывать метод обратного вызова при каждом обновлении базы данных, т. Е. Только для вызова операции обновления объекта.

Но onPostUpdate из PostUpdateEventListener вызывается при каждом вызове Jpa, т.е. независимо от работы БД. Это странное поведение для меня. Или слушатель ведет себя так же?

Я использую Hibernate 5.3.7 и не могу увидеть много подробной документации, кроме следующей ссылка

Также прикрепление классов, которые используются для регистрации моего пользовательского слушателя и требуемой конфигурации.

  1. Класс CustomEventListener:

    import javax.persistence.EntityManager;
    import javax.persistence.PersistenceContext;
    
    import org.hibernate.event.spi.PostUpdateEvent;
    import org.hibernate.event.spi.PostUpdateEventListener;
    import org.hibernate.persister.entity.EntityPersister;
    import org.springframework.stereotype.Component;
    
    @Component
    public class CustomEventListener implements PostUpdateEventListener {
    
        /**
         * 
         */
        private static final long serialVersionUID = 1L;
    
        public static final CustomEventListener INSTANCE = new CustomEventListener();
        @PersistenceContext
        private EntityManager entityManager;
        /* (non-Javadoc)
         * @see org.hibernate.event.spi.PostCollectionUpdateEventListener#onPostUpdateCollection(org.hibernate.event.spi.PostCollectionUpdateEvent)
         */
    
        @Override
        public boolean requiresPostCommitHanding(EntityPersister persister) {
            // TODO Auto-generated method stub
    
            return false;
        }
    
        /* (non-Javadoc)
         * @see org.hibernate.event.spi.PostUpdateEventListener#onPostUpdate(org.hibernate.event.spi.PostUpdateEvent)
         */
        @Override
        public void onPostUpdate(PostUpdateEvent event) {
            // TODO Auto-generated method stub
            System.out.println("hello");
        }
    
    }`
    
  2. Класс HibernateConfig: используется для настройки свойства hibernate.integrator_provider в существующей конфигурации

    import java.util.Collections;
    import java.util.Map;
    
    import org.hibernate.jpa.boot.spi.IntegratorProvider;
    import org.springframework.boot.autoconfigure.orm.jpa.HibernatePropertiesCustomizer;
    import org.springframework.stereotype.Component;
    
    /**
     * @author satyam.kaushik
     * @version  Last modified 09-Apr-2019
     */
    
    @Component
    public class HibernateConfig implements HibernatePropertiesCustomizer {
    
        @Override
        public void customize(Map<String, Object> hibernateProperties) {
            hibernateProperties.put("hibernate.integrator_provider",
                    (IntegratorProvider) () -> Collections.singletonList(MetadataExtractorIntegrator.INSTANCE));
        }
    }
    
  3. Класс MetadataExtractorIntegrator для регистрации прослушивателя `

    import org.hibernate.boot.Metadata;
    import org.hibernate.engine.spi.SessionFactoryImplementor;
    import org.hibernate.event.service.spi.EventListenerRegistry;
    import org.hibernate.event.spi.EventType;
    import org.hibernate.integrator.spi.Integrator;
    import org.hibernate.service.spi.SessionFactoryServiceRegistry;
    
    public class MetadataExtractorIntegrator implements Integrator {
    
        public static final MetadataExtractorIntegrator INSTANCE = new MetadataExtractorIntegrator();
    
        @Override
        public void integrate(Metadata metadata, SessionFactoryImplementor sessionFactory,
                SessionFactoryServiceRegistry serviceRegistry) {
    
            final EventListenerRegistry eventListenerRegistry = serviceRegistry.getService(EventListenerRegistry.class);
    
            eventListenerRegistry.appendListeners(EventType.POST_UPDATE, CustomEventListener.INSTANCE);
    
        }
    
        @Override
        public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
    
        }
    }`
    

    Я также пробовал другие встроенные слушатели, предоставляемые API, т.е. SaveOrUpdateEventListener или MergeEventListener, но у меня ничего не работает. Похоже, что слушатель вызывает каждый вызов JPA, а не только вызов обновления.

Также прикрепление журналов ниже для запроса Get, который вызывает проблему (то есть вызов метода слушателя, который не должен вызывать вызов)

0: 0: 0: 0: 0: 0: 0: 1 - - [09 / Apr / 2019: 16: 38: 38 +0530] "ОПЦИИ / rippsadm / rest / device? Sort-column = & sort- order = asc & page-no = 1 & page-size = 15 HTTP / 1.1 "200 -

0: 0: 0: 0: 0: 0: 0: 1 - - [09 / Apr / 2019: 16: 38: 38 +0530] "ОПЦИИ / rippsadm / rest / device / filter HTTP / 1.1" 200 -

0: 0: 0: 0: 0: 0: 0: 1 - - [09 / Apr / 2019: 16: 38: 41 +0530] "GET / rippsadm / rest / device / filter HTTP / 1.1" 200 1918

0: 0: 0: 0: 0: 0: 0: 1 - - [09 / Apr / 2019: 16: 38: 41 +0530] "GET / rippsadm / rest / device? Sort-column = & sort- order = asc & page-no = 1 & page-size = 15 HTTP / 1.1 "200 6422

1 Ответ

0 голосов
/ 10 апреля 2019
Solution : Customize the Handling of EventType.POST_UPDATE Events for the entities which doesn't need to post process but triggering update call to Jpa for each request.

Identify if any insert statement executed during the Get call by using show_sql=true. If yes then there can be multiple reasons including auditing, some setter method update the entity in services, Or some interceptor invoke an insert/update call etc.


In my case hibernate enver auditing was root cause.Setting show_sql=true was showing the hibernate insert query for one of audit managed entity and REVINFO hibernate enver default table.

 In my case this entity never need to post process.

Therefore I've added an if condition inside onPostUpdate method of Custom listener  to skip post processing for the entity resolved the issue.

@Override
    public void onPostUpdate(PostUpdateEvent event) {
if(!(event.getEntity().getClass().getTypeName().contains("<EntityName>"))) {
           //do your post processing logic
        }
  }   
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...