从非托管连接更改数据时的 JPA @Version 行为
JPA @Version behavior when data is changed from unmanaged connection
在 table Customer
上启用 @Version
当 运行 进行以下测试时
@Test
public void actionsTest1 () throws InterruptedException {
CustomerState t = customerStateRepository.findById(1L).get();
Thread.sleep(20000);
t.setInvoiceNumber("1");
customerStateRepository.save(t);
}
当 actionsTest1
正在睡觉时,我 运行 actionsTest2
将发票编号更新为 2。
@Test
public void actionsTest2 () throws InterruptedException {
CustomerState t = customerStateRepository.findById(1L).get();
t.setInvoiceNumber("2");
customerStateRepository.save(t);
}
当 actionsTest1 returns 休眠时,它也尝试更新,并获得 ObjectOptimisticLockingFailureException
按预期工作。
但是如果我 运行 actionsTest1
并且在它处于休眠状态时我打开一个 SQL 终端并进行
的原始更新
update customer
set invoice_number='3' where id=1
当 actionsTest1
returns 休眠时,它的版本控制机制没有捕捉到这种情况并将值更新回 1。
这是预期的行为吗?版本控制是否仅适用于 JPA 管理的连接?
Is that expected behavior?
是的。
Does versioning work only with connections managed by JPA?
不,它在使用任何其他方式更新数据时也有效。但是所有更新数据的东西都必须遵守乐观锁的规则:
- 每当执行任何更新时增加版本列
- (仅当其他进程也想检测并发更新时才需要):在每次更新时检查版本号自加载更新所基于的数据以来没有变化。
它按预期工作。如果您手动更新,您也必须更新您的版本。
如果您将 JPA 与 @Version 一起使用,JPA 会递增版本列。
要获得预期结果,您必须像这样编写语句
update customer set invoice_number='3', version=XYZ (mabye version+1) where id=1
自动休眠 increases/changes 数据库中 @Version
映射列中的值。
当您获取实体记录时,hibernate 会保留数据记录的副本以及 @Version
的值。在执行 merge
或 update
操作时,hibernate 检查 Version 中的当前值是否仍然相同,并与之前获取的实体副本匹配。
如果该值匹配,则意味着该实体不是脏的(未被任何其他事务更新)否则将抛出异常。
在 table Customer
上启用 @Version
当 运行 进行以下测试时
@Test
public void actionsTest1 () throws InterruptedException {
CustomerState t = customerStateRepository.findById(1L).get();
Thread.sleep(20000);
t.setInvoiceNumber("1");
customerStateRepository.save(t);
}
当 actionsTest1
正在睡觉时,我 运行 actionsTest2
将发票编号更新为 2。
@Test
public void actionsTest2 () throws InterruptedException {
CustomerState t = customerStateRepository.findById(1L).get();
t.setInvoiceNumber("2");
customerStateRepository.save(t);
}
当 actionsTest1 returns 休眠时,它也尝试更新,并获得 ObjectOptimisticLockingFailureException
按预期工作。
但是如果我 运行 actionsTest1
并且在它处于休眠状态时我打开一个 SQL 终端并进行
update customer
set invoice_number='3' where id=1
当 actionsTest1
returns 休眠时,它的版本控制机制没有捕捉到这种情况并将值更新回 1。
这是预期的行为吗?版本控制是否仅适用于 JPA 管理的连接?
Is that expected behavior?
是的。
Does versioning work only with connections managed by JPA?
不,它在使用任何其他方式更新数据时也有效。但是所有更新数据的东西都必须遵守乐观锁的规则:
- 每当执行任何更新时增加版本列
- (仅当其他进程也想检测并发更新时才需要):在每次更新时检查版本号自加载更新所基于的数据以来没有变化。
它按预期工作。如果您手动更新,您也必须更新您的版本。
如果您将 JPA 与 @Version 一起使用,JPA 会递增版本列。
要获得预期结果,您必须像这样编写语句
update customer set invoice_number='3', version=XYZ (mabye version+1) where id=1
自动休眠 increases/changes 数据库中 @Version
映射列中的值。
当您获取实体记录时,hibernate 会保留数据记录的副本以及 @Version
的值。在执行 merge
或 update
操作时,hibernate 检查 Version 中的当前值是否仍然相同,并与之前获取的实体副本匹配。
如果该值匹配,则意味着该实体不是脏的(未被任何其他事务更新)否则将抛出异常。