2011-03-14 123 views
7

我有两个班说Foo和Bar映射为@OneToOne(双向)使用Hibernate(3.6.1最终)与JPA(2.0)一样 -更新休眠手动版

@Entity 
public class Foo{ 
    @Id 
    private Long id; 

    @OneToOne(cascade = CascadeType.ALL, mappedBy = "foo") 
    private Bar bar; 

    @OneToOne(cascade = CascadeType.ALL, mappedBy = "foo") 
    private Qux qux; 

    @Version 
    private int version; 

    // getters and setters omitted 
} 

@Entity 
public class Bar{ 
    @Id 
    private Long id; 

    @OneToOne 
     @JoinColumn(name = "foo_id", nullable = false) 
    private Foo foo; 

    // getters and setters omitted 
} 

@Entity 
public class Qux { 
    @Id 
    private Long id; 

    @OneToOne 
     @JoinColumn(name = "foo_id", nullable = false) 
    private Foo foo; 

    // getters and setters omitted 
} 

注意 - 酒吧和Qux没有@Version

如果我们更新Bar,那么hibernate不会增加Foo的版本,Qux也是一样。但是我们的业务逻辑需要 - 如果有人更新Foo中的Bar,并且其他线程正在尝试更新同一个Foo的Qux,但没有更新Bar,反之亦然,则此类更新应该失败。
因为如果我们更新Bar,hibernate不会更新Foo的版本属性,所以如果我们更新Bar和Qux,我们决定手动更新Foo的版本(我知道这很奇怪,不推荐)。
它工作得很好..但我担心一些并发的角落情况可能会失败,或将有意想不到的行为。
为此目的进行这种类型的版本调整是否安全?或有任何其他更好的这种另类(我已经尝试过乐观/悲观力increament)

回答

10

正确的方法来强制版本更新如下:

em.lock(entity, LockModeType.OPTIMISTIC_FORCE_INCREMENT); 

它打算在这样的使用案例。

其他方法EntityManager也可以使用LockModeType也可以使用。

+0

但要使用此我需要Bar和Qux中的版本属性,对不对? – Premraj

+0

@Premraj:是的.. – axtavt

+0

我正在尝试这个代码: 'Foo entity = new Foo(); em.persist(foo); int oldVersion = entity.getVersion(); em.lock(entity,LockModeType.OPTIMISTIC_FORCE_INCREMENT); return oldVersion == entity.getVersion();' 我希望这是错误的,但它是真实的。 –