问题描述
我有一个关于使用弹簧数据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 (将#修改为@)