【问题标题】:Why does Hibernate entity manager perform insert instead of update when dettached entity version property is null?为什么当分离的实体版本属性为空时,Hibernate entitymanager 执行插入而不是更新?
【发布时间】:2015-02-04 19:32:55
【问题描述】:

我注意到,当您有一个具有 @Version 属性的实体并尝试通过手动实例化该实体、将其 id 设置为现有 id 并调用 merge() 来更新记录时,Hibernate 执行插入而不是更新。我认为这是因为手动实例化对象的版本属性为空。标识符的存在是否足以让 Hibernate 确定它应该执行更新?

示例代码:

假设数据库中有一条 id=1 的记录,并且 MyEntity 有一个带有 @Version 的属性版本。

MyEntity e = new MyEntity();
e.setId(1);
e.setName("some updated value");

entityManager.merge(e);

这最终会执行插入而不是更新。

MyEntity 类似于:

@Entity
public class MyEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Integer id;

    @Column("name")
    String name;

    @Version
    Integer version;

}

如果我删除 @Version,它会按预期工作,id=1 的记录会更新。

【问题讨论】:

  • 你必须提供完整的MyEntity代码
  • 嗯,重要的一点只有两个属性。一个 Id 和一个 Version 属性。我将编辑问题以澄清。

标签: java hibernate jpa orm


【解决方案1】:

The documentation 确认您的经验:

对于分离的实例,版本或时间戳属性永远不应为空。 Hibernate 将检测任何具有空版本或时间戳的实例作为瞬态,而不管指定了哪些其他未保存值策略。

即使它使用 ID 来确定实体是否已分离,尝试将实体与空版本合并也会导致乐观锁定异常。您根本不应该将分离的对象与空版本合并。这违背了使用乐观锁定的目的。

【讨论】:

  • 谢谢。这就是我一直在寻找的。顺便说一句,我知道它违背了乐观锁定的目的,但我在想,也许 Hibernate 可以将空版本属性转换为“最新版本”,从而覆盖乐观锁定,但无论如何这可能不是一个好主意。我猜有点危险。
猜你喜欢
  • 2016-07-14
  • 1970-01-01
  • 2011-07-03
  • 2021-08-02
  • 1970-01-01
  • 2021-05-15
  • 2020-12-14
  • 1970-01-01
  • 2015-12-02
相关资源
最近更新 更多