在使用SpringDataREST存储库时,如何确定RESTful资源的哪些属性在保存之前已更改?
如果我有SpringDataREST发布的以下资源在使用SpringDataREST存储库时,如何确定RESTful资源的哪些属性在保存之前已更改?,spring,spring-data,spring-data-rest,Spring,Spring Data,Spring Data Rest,如果我有SpringDataREST发布的以下资源 {“状态”:“空闲”} 我如何应对更改属性状态值的修补程序或PUT?其想法是基于属性更改触发一些服务器进程 理想情况下,这将在保存之前发生,并且可以将资源的新版本与以前的持久化版本进行比较。您通常会使用@RepositoryEventHandler连接事件逻辑-请参阅 我不知道有什么函数可以直接获取更改的属性。但是如果使用handlebeforestave处理程序,则可以加载持久实体(旧状态)并将其与新状态进行比较- @Reposito
{“状态”:“空闲”}
我如何应对更改属性状态值的修补程序或PUT?其想法是基于属性更改触发一些服务器进程
理想情况下,这将在保存之前发生,并且可以将资源的新版本与以前的持久化版本进行比较。您通常会使用@RepositoryEventHandler
连接事件逻辑-请参阅
我不知道有什么函数可以直接获取更改的属性。但是如果使用handlebeforestave
处理程序,则可以加载持久实体(旧状态)并将其与新状态进行比较-
@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
}
}
}
请注意,您需要从当前EntityManager中分离newPerson。否则,我们将在调用findOne时获取缓存的person对象,并且我们无法将更新版本与当前数据库状态进行比较
使用Eclipselink时的备选方案
如果您使用的是eclipselink,您还可以更高效地找到应用于实体的更改,从而避免重新加载-请参阅
UnitOfWorkChangeSet changes=entityManager.unwrap(UnitOfWork.class).getCurrentChanges();
ObjectChangeSet objectChanges=changes.getObjectChangeSetForClone(newPerson);
List changedAttributeNames=objectChanges.getChangedAttributeNames();
if(objectChanges.hasChangeFor(“名称”)){
ChangeRecordChangeRecordForName=objectChanges.GetChangesFrattributeNamed(“名称”);
字符串oldValue=changeRecordForName.getOldValue();
}
这不起作用。在您的示例中,newPerson和currentPerson最终是相同的Person实例。我无法获取数据库中存在的“currentPerson”。这就好像Spring Data Rest已经将newPerson附加到JPA会话,因此后面的查询将获得新值。如果我将EntityManager注入到带有@PersistenceContext注释的PersonEventHandler中,并在currentPerson查询之前执行EntityManager.detach(newPerson),这将按预期工作。如果您更新代码以反映这一点,我将接受您的回答。感谢@GabrielBauman的提示-您完全正确-我们的查找程序不会进入数据库,但会返回已在EntityManager中注册的person对象-以便能够与我们之前需要分离对象的当前状态进行比较。我相应地更新了我的答案。
UnitOfWorkChangeSet changes = entityManager.unwrap(UnitOfWork.class).getCurrentChanges();
ObjectChangeSet objectChanges = changes.getObjectChangeSetForClone(newPerson);
List<String> changedAttributeNames = objectChanges.getChangedAttributeNames();
if (objectChanges.hasChangeFor("name")) {
ChangeRecord changeRecordForName = objectChanges.getChangesForAttributeNamed("name");
String oldValue = changeRecordForName.getOldValue();
}