【问题标题】:Jpa - Hibernate @Version incorrectly incrementedJpa - Hibernate @Version 错误地递增
【发布时间】:2011-09-30 10:34:21
【问题描述】:

我使用 jpa 和 hibernate (3.2.7) 作为 orm 实现。 我有一个实体被修改然后合并。 我在这个实体上也有一个@EntityListeners 以确保某些属性被重视。

如果我在合并之前更改了一个值,然后在 Listener 内的 @PreUpdate 方法中更改回该值,设置原始值,我在实体结果上的版本会增加,但在数据库版本上具有以前的值。 我认为这是由于对象没有改变,所以在 db 上它没有更新,但实体上的版本已经增加而在刷新后没有恢复。

为了更好地解释,我有这个对象:

@Entity
@EntityListeners({MyListener.class})
public class MyEntity {

    @Id 
    @GeneratedValue(strategy=GenerationType.AUTO)   
    private Long id;

    private String myValue;

    @Version    
    private Long version ;
}

还有这个监听器:

public class MyListener {

    @PreUpdate
    public void preUpdate(MyEntity ua) { 
        ua.setMyValue("default");
    }
}

现在假设我在 db 上有一个具有以下值的对象:(id=1, myValue='defalut', version=1)。我读取了这个对象,分离,将它传递给客户端并使用 myValue='new' 将其取回并执行合并操作(侦听器将 myValue 更改为'default',因此对象结果未修改为 db),刷新并退出事务(所以承诺)。 之后,我在我的对象上找到 version=2,但在 db 上找到 version=1。

这是一个休眠错误吗?还是 Jpa 错误?

【问题讨论】:

  • 您能谈谈您的方法调用层次结构和调用顺序吗?也许您的合并方法在更新方法之前起作用。
  • 我猜 hibernate 脏检查返回 false 所以你的对象不会触及数据库(没有生成更新查询),但是当你第一次调用 setter 时,hibernate 可能会增加你的版本字段。恕我直言,版本字段仅应在更新值写入数据库时​​递增。这可能是一个休眠错误。

标签: hibernate jpa version


【解决方案1】:

我会说这是一种预期的行为。根据Hibernate manual@PreUpdate 是“在数据库更新操作之前执行的。”。所以,Hibernate 已经知道它必须通过运行脏检查并让它返回 true 来执行 UPDATE。

脏检查不能在@PreUpdate 之后发生,因为除非脏检查为真,否则 Hibernate 不应调用 @PreUpdate。如果要运行更新,版本应该增加。

您是否考虑过为@PrePersist 使用侦听器,而不是@PreUpdate?我相信这在这个过程中已经足够早了,它将是预先脏检查,因此有你想要的行为。

【讨论】:

    【解决方案2】:

    对我来说,这看起来像是违反规范。或者也许这措辞太强硬,最好是说这种极端情况没有足够清楚地说明。 JPA 1.0(Hibernate 3.2.7 是其中一种实现)规范清楚地说明了何时应该更新版本:

    版本属性由持久化提供者运行时更新 当对象被写入数据库时​​。

    同时在被调用实体中设置基本属性是大声的(JPA 2.0):

    生命周期回调方法可以修改非关系状态 调用它的实体。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-08-10
      • 2016-09-17
      • 2020-01-03
      • 1970-01-01
      • 2019-10-04
      • 2015-04-18
      • 2015-03-14
      • 1970-01-01
      相关资源
      最近更新 更多