Spring Data JPA + Hibernate:开放式锁定无法按预期进行

问题描述

我有一个关于使用弹簧数据jpa和休眠状态进行乐观锁定的问题。我知道不同锁定类型的理论背景,以及乐观锁定应如何工作,但即使是简单的测试也不会引发任何锁定异常。

我有一个带有version属性的简单实体:

@Entity
@Table( name = "DOK_AUDIT",schema = "ORACLE" )
@SuppressWarnings( "unused" )
public class DocAudit {

    @Id
    @GeneratedValue( strategy = GenerationType.IDENTITY )
    @Column( name = "AUDIT_ID" )
    private Long id;

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

    @Column( name = "CHANGE_USER" )
    private String changeUser;
}

我创建了一种简单的事务服务方法,其中应更新一行

@Transactional
public void changeWithId(final Long auditId) {
    Preconditions.checkArgument(auditId != null,"auditId can't be null");

    final DocAudit auditById = auditRepository.getAuditById(auditId);
    auditById.setName("xxx");
}

现在,在事务提交之前,我在函数的最后一行添加了一个调试器断点,并且将执行更新语句。

当调试器到达这一点时,我更改了数据库中的行并增加了版本。 现在,当恢复应用程序时,我可以看到将执行update语句,并使用where子句中的更正的版本列

update oracle.dok_audit set version=?,change_user=?,audit_name=?,audit_start_date=? where audit_id=? and version=?

由于where子句与数据库中的任何行都不匹配,因此update语句返回0(未更改任何行),但不会引发ObjectOptimisitcLockingException。

据我所知,hibernate / spring数据存储库现在应该抛出此异常,因为版本不匹配和更新不会影响任何行。

我想念什么?

当我对不同的事务执行读取和更新时,将发生乐观的锁定执行。在下面的示例中,我在保存功能之前添加了一个断点,然后再次更改了数据库中的版本

// getAuditById is transactional
final DocAudit audit = auditService.getAuditById(2L);
audit.setName("changed");
// save audit is another transaction
auditService.saveAudit(audit);

当我现在使用此分离的实体调用saveAudit(调用存储库的保存功能)时,实体管理器必须合并分离的实体。当从数据库中选择实体以将其重新附加到上下文时,由于版本不匹配,将引发光学标记锁定异常。

可以,但是为什么在一个事务中更改实体时,第一个示例中的光学标记锁定不起作用?

谢谢 塞巴斯蒂安

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...