Jpa - Hibernate @Version错误地增加了

时间:2011-09-30 10:34:21

标签: hibernate jpa version

我正在使用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。上找到版本= 1。

这是一个hibernate错误吗?还是一个Jpa bug?

2 个答案:

答案 0 :(得分:2)

我想说这是一种预期的行为。根据{{​​3}},@PreUpdate是“在数据库更新操作之前执行的”。因此,Hibernate已经发现它必须通过运行脏检查来执行UPDATE,并使其返回true。

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

您是否考虑过使用@PrePersist而非@PreUpdate的听众?我相信这个过程的早期就是预先检查,因此有你想要的行为。

答案 1 :(得分:0)

对我来说,它看起来像规范违规。或者这可能是措辞过于强烈,可能更好地说这样的角落案例并没有明确规定。当版本应该更新时,JPA 1.0(Hibernate 3.2.7是其中一个实现)规范非常清楚:

  

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

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

  

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