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

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
      }
   }
}

Thanks Marcel Overdijk, for creating the ticket -> https://jira.spring.io/browse/DATAREST-373

I saw the other workarounds for this issue and want to contribute my workaround as well, cause I think it´s quite simple to implement.

First, set a transient flag in your domain model (e.g. Account):

@JsonIgnore
@Transient
private boolean passwordReset;

@JsonIgnore
public boolean isPasswordReset() {
    return passwordReset;
}

@JsonProperty
public void setPasswordReset(boolean passwordReset) {
    this.passwordReset = passwordReset;
}

Second, check the flag in your EventHandler:

@Component
@RepositoryEventHandler
public class AccountRepositoryEventHandler {

    @Resource
    private PasswordEncoder passwordEncoder;

    @HandleBeforeSave
    public void onResetPassword(Account account) {
        if (account.isPasswordReset()) {
            account.setPassword(encodePassword(account.getPassword()));
        }
    }

    private String encodePassword(String plainPassword) {
        return passwordEncoder.encode(plainPassword);
    }

}

Note: For this solution you need to send an additionally resetPassword = true parameter!

For me, I´m sending a HTTP PATCH to my resource endpoint with the following request payload:

{
    "passwordReset": true,
    "password": "someNewSecurePassword"
}

You're currently using a spring-data abstraction over hibernate. If the find returns the new values, spring-data has apparently already attached the object to the hibernate session.

I think you have three options:

  1. Fetch the object in a separate session/transaction before the current season is flushed. This is awkward and requires very subtle configuration.
  2. Fetch the previous version before spring attached the new object. This is quite doable. You could do it in the service layer before handing the object to the repository. You can, however not save an object too an hibernate session when another infect with the same type and id it's known to our. Use merge or evict in that case.
  3. Use a lower level hibernate interceptor as described here. As you see the onFlushDirty has both values as parameters. Take note though, that hibernate normally does not query for previous state of you simply save an already persisted entity. In stead a simple update is issued in the db (no select). You can force the select by configuring select-before-update on your entity.