我正在尝试在@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
方法获取旧实体,但这会返回新事件。可能是因为当前会话中的Hibernate/Repository缓存。
有办法获取旧实体吗?
我需要它来确定给定的属性是否被更改。如果属性发生更改,我需要执行一些操作。
如果使用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
}
}
}
感谢Marcel Overdijk,创建门票-
我看到了这个问题的其他解决方法,并且也想贡献我的解决方法,因为我认为它很容易实现。
首先,在您的域模型(例如帐户)中设置一个瞬态标志:
@JsonIgnore
@Transient
private boolean passwordReset;
@JsonIgnore
public boolean isPasswordReset() {
return passwordReset;
}
@JsonProperty
public void setPasswordReset(boolean passwordReset) {
this.passwordReset = passwordReset;
}
其次,检查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);
}
}
注意:对于这个解决方案,您需要额外发送一个resetPassword=true
参数!
对我来说,我正在向我的资源终结点发送一个HTTPPATCH,其中包含以下请求有效负载:
{
"passwordReset": true,
"password": "someNewSecurePassword"
}
您目前正在Hibernate上使用spring-data抽象。如果查找返回新值,则spring-data显然已经将对象附加到Hibernate会话。
我想你有三个选择:
merge
或驱逐
。onFlushDirty
有两个值作为参数。但是请注意,Hibernate通常不会查询你以前的状态,只是保存一个已经持久化的实体。取而代之的是在数据库中发出一个简单的更新(没有选择)。您可以通过在您的实体上配置选择前更新来强制选择。