如何在@HandleBeforeSave事件中获取旧实体值以确定属性是否已更改?

2022-09-01 13:18:18

我正在尝试在事件中获取旧实体。@HandleBeforeSave

@Component
@RepositoryEventHandler(Customer.class)
public class CustomerEventHandler {

    private CustomerRepository customerRepository;

    @Autowired
    public CustomerEventHandler(CustomerRepository customerRepository) {
        this.customerRepository = customerRepository;
    }

    @HandleBeforeSave
    public void handleBeforeSave(Customer customer) {
        System.out.println("handleBeforeSave :: customer.id = " + customer.getId());
        System.out.println("handleBeforeSave :: new customer.name = " + customer.getName());

        Customer old = customerRepository.findOne(customer.getId());
        System.out.println("handleBeforeSave :: new customer.name = " + customer.getName());
        System.out.println("handleBeforeSave :: old customer.name = " + old.getName());
    }
}

在这种情况下,我尝试使用该方法获取旧实体,但这会返回新事件。可能是因为当前会话中的休眠/存储库缓存。findOne

有没有办法获得旧实体?

我需要这个来确定给定的属性是否被更改。如果属性发生变化,我需要执行一些操作。


答案 1

如果使用Hibernate,您只需从会话中分离新版本并加载旧版本即可:

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

答案 2

感谢 Marcel Overdijk 创建票证 -> https://jira.spring.io/browse/DATAREST-373

我看到了此问题的其他解决方法,并希望也贡献我的解决方法,因为我认为它的实现非常简单。

首先,在域模型中设置一个瞬态标志(例如帐户):

@JsonIgnore
@Transient
private boolean passwordReset;

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

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

其次,检查事件处理程序中的标志:

@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);
    }

}

注意:对于此解决方案,您需要发送一个额外的参数!resetPassword = true

对于我来说,我正在向我的资源终端节点发送 HTTP PATCH,其中包含以下请求负载:

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

推荐