在使用SpringDataREST存储库时,如何确定RESTful资源的哪些属性在保存之前已更改?

在使用SpringDataREST存储库时,如何确定RESTful资源的哪些属性在保存之前已更改?,spring,spring-data,spring-data-rest,Spring,Spring Data,Spring Data Rest,如果我有SpringDataREST发布的以下资源 {“状态”:“空闲”} 我如何应对更改属性状态值的修补程序或PUT?其想法是基于属性更改触发一些服务器进程 理想情况下,这将在保存之前发生,并且可以将资源的新版本与以前的持久化版本进行比较。您通常会使用@RepositoryEventHandler连接事件逻辑-请参阅 我不知道有什么函数可以直接获取更改的属性。但是如果使用handlebeforestave处理程序,则可以加载持久实体(旧状态)并将其与新状态进行比较- @Reposito

如果我有SpringDataREST发布的以下资源

{“状态”:“空闲”}

我如何应对更改属性
状态值的修补程序或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();

        }