休眠 :merge() over update() 的缺点

2022-09-01 13:03:33

我遇到了由Hibernate抛出的问题。NonUniqueObjectException

阅读文档和这篇博客文章,我替换了从 到 的调用,它解决了问题。update()merge()

我相信我理解异常的原因,以及为什么更改方法可以解决问题,即断开连接的对象和会话边界。

我的问题是:鉴于它将始终解析为会话对象,或者如果它不存在,则检索它,调用merge()通常是比?merge()update()

使用over的缺点是什么?merge()update()


答案 1

调用 merge() 通常是比 update() 更安全的替代方法吗?

作为避免非唯一对象异常的一种方式,是的。我认为这解释了为什么JPA不允许更新方法。

使用 merge() 而不是 update() 的缺点是什么?

未通知的用户可能认为他或她有一个新的托管实体。类似的东西

// myEntity (passed as parameter does not become managed)
// Only the one returned by the merge operation is a managed entity
session.merge(myEntity);

// "newValue" is not commited because myEntity is not managed
myEntity.setMyProperty("newValue");

如果您的持久性上下文不包含您的实体,则可能不希望在更新之前选择默认行为。但它是可以避免的

  • 添加版本(@Version)列。0 或 NULL 版本表示实例是新的,必须插入,而不是更新
  • 使用休眠拦截器
  • 如果确定要更新而不是插入,可以使用以下方法

...

public void updateMyEntity(MyEntity updateableMyEntity);

    // load does not hit the database
    MyEntity myEntity = (MyEntity) session.load(MyEntity.class, updateableMyEntity.getId());

    BeanUtils.copyProperties(myEntity, updateableMyEntity);

}

这样,您就可以在不合并或更新方法的情况下更新实体。有关详细信息,请参阅此问题:在 Hibernate 上更新分离对象的某些字段的最佳方法?


答案 2

如果您确定会话不包含具有相同标识符的已持久化实例,请使用 update();如果您希望在不考虑会话状态的情况下随时合并修改,请使用 merge()。换句话说,update() 通常是您在新会话中调用的第一个方法,可确保分离实例的重新附加是执行的第一个操作。


推荐