我有一个在其中一个字段上使用@version的实体,我希望实现这一点,如果两个事务在同一时间修改此实体,一个将失败(并获得乐观锁定异常)而另一个将成功。< / p>
当我在单个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 ... 任何想法?
答案 0 :(得分:1)
如果在两个不同的 hibernate会话(通常在两个不同的JVM或两个不同的主机上)中有两个DeploymentLock
实例,每个实例具有相同的version
值,然后,您调用的第二个更新应该抛出HibernateOptimisticLockingFailureException
。
基本上hibernate正在做类似的事情:
UPDATE DeploymentLock SET deploymentCounter = ..., version = 2 WHERE version = 1
然后,如果更新未更改该行,则抛出异常。
您确定两个不同的JVM(或两个会话)具有相同的具有相同version
值的实例吗?可能是某个地方有refresh()
您没想到或者竞争条件导致第二个实例查询返回更新后的DeploymentLock
?
可能会在更新之前添加一些日志记录或println
调试以打印版本值。如果它确实显示版本相同,那么您可以编辑帖子以显示您如何进行更新通话吗?