当一个不存在的实体被传递给 merge() 时,Hibernate 意外地发出 INSERT 而不是抛出 javax.persistence.OptimisticLockException

Tin*_*iny 5 merge hibernate jpa optimistic-locking

客户端应用程序提供了一个陈旧的实体,该实体将被 Hibernate 合并。举个很简单的例子。

public Entity update(Entity entity) {
    return entityManager.contains(entity) ? entity : entityManager.merge(entity);
}
Run Code Online (Sandbox Code Playgroud)

Entity例如,是由 Web 应用程序提供的分离的、陈旧的实体。该方法在活动的 JTA 事务(或本地资源)中执行。

乐观锁已通过引入 @Version在给定的实体中字段,。

当要合并的实体已经被删除时,javax.persistence.OptimisticLockException预计会抛出这不会发生的情况。Hibernate 执行INSERT,这是完全出乎意料的。插入一个陈旧的实体而不是抛出javax.persistence.OptimisticLockException是有悖于锁定的。

“插入或更新”是一个分开的故事,应该通过抛出 javax.persistence.OptimisticLockExceptionmerge(),如果实现了乐观锁定,如果过时或已删除(不存在)的实体被传递给。

javax.persistence.OptimisticLockException如果过时或已删除/不存在的实体被传递给,EclipseLink 会按预期抛出merge()

javax.persistence.OptimisticLockException当一个陈旧或不存在的实体被传递给时,有没有办法让 Hibernate 抛出,merge()

我希望应该有一些可配置的属性 persistence.xml全局应用程序范围内应用它,或者使用注释将它应用到特定实体。

我目前使用的是 Hibernate 5.0.5 final。


更新到 Hibernate 5.0.6 最终版。

小智 0

尝试 EntityManager.refresh 而不是 EntityManager.merge,并验证实体是否具有 id 值,如果是,则设置新值,然后在 EntityManager.merge 后,如果没有,则实体已被删除

像这样的东西

public Entity update(Entity entity) {

    entityManager.refresh(entity);

    if (entity.getId() != null) {
        // my entity is in database
        // set my changes in entity
        return entityManager.merge(entity);
    } else {
        // my entity has been deleted
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)