How to get old entity value in @HandleBeforeSave event to determine if a property is changed or not?

后端 未结 10 1716
余生分开走
余生分开走 2020-12-13 13:33

I\'m trying to get the old entity in a @HandleBeforeSave event.

@Component
@RepositoryEventHandler(Customer.class)
public class CustomerEventHan         


        
相关标签:
10条回答
  • 2020-12-13 14:25

    The following worked for me. Without starting a new thread the hibernate session will provide the already updated version. Starting another thread is a way to have a separate JPA session.

    @PreUpdate

    Thread.start {
        if (entity instanceof MyEntity) {
            entity.previous = myEntityCrudRepository.findById(entity?.id).get()
        }
    }.join()
    

    Just let me know if anybody would like more context.

    0 讨论(0)
  • 2020-12-13 14:26

    Spring Data Rest can't and likely won't ever be able to do this due to where the events are fired from. If you're using Hibernate you can use Hibernate spi events and event listeners to do this, you can implement PreUpdateEventListener and then register your class with the EventListenerRegistry in the sessionFactory. I created a small spring library to handle all of the setup for you.

    https://github.com/teastman/spring-data-hibernate-event

    If you're using Spring Boot, the gist of it works like this, add the dependency:

    <dependency>
      <groupId>io.github.teastman</groupId>
      <artifactId>spring-data-hibernate-event</artifactId>
      <version>1.0.0</version>
    </dependency>
    

    Then add the annotation @HibernateEventListener to any method where the first parameter is the entity you want to listen to, and the second parameter is the Hibernate event that you want to listen for. I've also added the static util function getPropertyIndex to more easily get access to the specific property you want to check, but you can also just look at the raw Hibernate event.

    @HibernateEventListener
    public void onUpdate(MyEntity entity, PreUpdateEvent event) {
      int index = getPropertyIndex(event, "name");
      if (event.getOldState()[index] != event.getState()[index]) {
        // The name changed.
      }
    }
    
    0 讨论(0)
  • 2020-12-13 14:27

    If using Hibernate, you could simply detach the new version from the session and load the old version:

    @RepositoryEventHandler 
    @Component
    public class PersonEventHandler {
    
      @PersistenceContext
      private EntityManager entityManager;
    
      @HandleBeforeSave
      public void handlePersonSave(Person newPerson) {
          entityManager.detach(newPerson);
          Person currentPerson = personRepository.findOne(newPerson.getId());
          if (!newPerson.getName().equals(currentPerson.getName)) {
              //react on name change
          }
       }
    }
    
    0 讨论(0)
  • 2020-12-13 14:32

    Don't know if you're still after an answer, and this is probably a bit 'hacky', but you could form a query with an EntityManager and fetch the object that way ...

    @Autowired
    EntityManager em;
    
    @HandleBeforeSave
    public void handleBeforeSave(Customer obj) {
       Query q = em.createQuery("SELECT a FROM CustomerRepository a WHERE a.id=" + obj.getId());
       Customer ret = q.getSingleResult();
       // ret should contain the 'before' object...
    }
    
    0 讨论(0)
提交回复
热议问题