2

我有一个在它的一个字段上使用@version 的实体,我想实现如果两个事务同时修改这个实体,一个会失败(并获得乐观锁异常),另一个会成功。

当我在单个 JVM 上运行此测试时,这工作正常,但是当我在集群环境中运行时,两个事务成功并且没有抛出乐观锁。

public class DeploymentLock  {

    @Column(name = "DEPLOYMENT_COUNTER")
    private Long deploymentCounter;

    @Version
    @Column(name = "ENTITY_VERSION")
    private Long version;
    ...
}

我错过了什么吗?我需要在@Version 下使用“@Generated(GenerationTime.ALWAYS)”吗?

顺便说一句,我在我的应用程序中使用 Spring 和 hibrnate ......知道吗?

4

1 回答 1

1

如果您有两个不同DeploymentLock休眠会话内部的两个实例(通常在两个不同的 JVM 或两个不同的主机上),每个实例具有相同的值,那么您调用的第二个更新应该 throw 。versionHibernateOptimisticLockingFailureException

基本上hibernate正在做类似的事情:

UPDATE DeploymentLock SET deploymentCounter = ..., version = 2 WHERE version = 1

然后,如果更新没有更改行,则会引发异常。

您确定两个不同的 JVM(或两个会话)具有相同version值的相同实例吗?是不是有一个refresh()你没想到的地方,或者竞争条件导致第二个实例查询返回更新的DeploymentLock

也许添加一些日志记录或println调试以在更新之前打印版本值。如果确实显示版本相同,那么您可以编辑您的帖子以显示您如何进行更新调用吗?

于 2012-06-05T16:40:39.407 回答