当分离的实体版本 属性 为空时,为什么 Hibernate entitymanager 执行插入而不是更新?

Why does Hibernate entity manager perform insert instead of update when dettached entity version property is null?

我注意到,当您有一个带有@Version 属性 的实体并且您尝试通过手动实例化该实体、将其 id 设置为现有 id 并调用 merge() 来更新记录时, Hibernate 执行插入而不是更新。我假设这是因为版本 属性 在手动实例化的对象上为 null。标识符的存在是否足以让 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 的记录。

The documentation 确认您的体验:

A version or timestamp property should never be null for a detached instance. Hibernate will detect any instance with a null version or timestamp as transient, irrespective of what other unsaved-value strategies are specified.

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