Spring Data JpaRepository save() 方法的副作用

5

我注意到在spring-data的JpaRepository中,使用save(T entity)方法时出现了非常奇怪的行为。

我有一个实体Foo foo,并尝试使用仓库fooRepository.save(foo)来保存它。我的问题是,在保存后,我传递给save()方法的foo实例发生了变化。我不希望这种情况发生,并且很奇怪我找不到任何相关的问题。

这是预期的行为吗?

1个回答

7
我们可以通过首先查看CrudRepository的Javadoc来尝试理解您的观察结果:

保存给定的实体。使用返回的实例进行进一步的操作,因为保存操作可能已完全更改了实体实例。

这里可能的一个解释是,当您保存时,一些其他线程或进程也修改了基础实体。 这里是save()方法实际执行的内容:
@Transactional
@Override
public <S extends T> S save(S entity) {

    if (entityInformation.isNew(entity)) {
        em.persist(entity);
        return entity;
    } else {
        return em.merge(entity);   // <-- this is your use case
    }
}

它将调用em.merge(),这将返回数据库记录/实体中已进行的任何新底层更改。因此,您应该检查是否还有其他内容在后台更新此实体。


@SergiiBishyr 这种语言可能是含糊不清的。声明 save() 可能已经改变了底层实体并不一定意味着你的代码就是在做这个改变。 - Tim Biegeleisen
令我困惑的是短语“使用返回的实例”。然而,在我的情况下,方法执行完成后,返回的实例和我传递给该方法的实例是相等的。 - Sergii Bishyr
1
那么在这种情况下,您应该检查已为实体定义的equals()合同。例如,如果equals仅检查主键,则两个对象可能是“相等的”。 - Tim Biegeleisen
@SergiiBishyr,你上面的评论似乎与你原来提出问题的陈述相矛盾。如果在“保存(save())”之前和之后确实没有任何变化,那么你最初的问题就不存在了。 - Tim Biegeleisen
不是一样的。从save()方法返回的实体实例和我传递给save()方法的实例是相同的。但是只有在执行save方法后它们才会相等,因为它会改变参数的状态。 - Sergii Bishyr
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接