@Version为null时乐观锁失败

问题描述 投票:0回答:2

我正在编写一些代码来生成序列号。我将读取并更新数据库中的一条记录,该记录保存下一个要生成的数字。由于我期望有不同的线程访问此记录,因此我只是将 @Version 标签添加到同一实体的 Timestamp 字段中,然后控制可能出现的 OptimisticLockExceptions。

此外,我的数据库中会有几条这样的记录,保存不同的序列号,可以根据业务创建或删除它们。

域对象如下所示:

@Entity
@Table(name="Preferences")
public class Preferences implements Serializable, DomainObject {
...
...
@Column(name="nextSerial")
private String nextSerial;

@Version
@Column(name="RefreshDate")
private Timestamp refreshDate;
...

直到这里一切正常,当共享相同数据的另一个应用程序创建首选项记录时,问题就出现了。构建此应用程序时,@Version 列不存在,因此它将创建带有 Null 值作为刷新日期的记录。

我知道这一点,我尝试设置刷新日期并更新记录,还尝试删除并再次创建记录,但无论如何,我都会收到如下异常:

org.springframework.orm.jpa.JpaOptimisticLockingFailureException: 异常 [EclipseLink-5001](Eclipse 持久性服务 - 2.6.1.v20150916-55dc7c3): org.eclipse.persistence.exceptions.OptimisticLockException 异常 尝试删除该对象。 [com.core.domain.Preferences@5e092f04],但它没有版本 身份映射中的编号。

所以我的问题是,我该如何从我的应用程序中处理这个问题?在数据库中使用触发器来确保非空 @Version 是不可取的,更改其他应用程序也是不可取的。

java spring-data optimistic-locking
2个回答
5
投票

您可以使用数据库手段在创建时为refreshDate设置默认值吗?喜欢

VERSION BIGINT NOT NULL DEFAULT 1 -- 对于数字版本

RefreshDate TIMESTAMP NOT NULL DEFAULT now() - 适合您的情况


0
投票

我在 spring-data-mongo 上遇到了类似的问题 - 我通过实体类实现 Persistable 接口解决了它,方法如下:

public class MyEntity extends Persistable<String> {
    @Version
    private Long version;

    @Override
    public String getId() {
        return get_id();
    }

    @Override
    public boolean isNew() {
        return isNull(getId());
    }
}

对我来说它很有帮助 - 在更新现有文档时,版本字段刚刚开始出现 0 值。诀窍是默认情况下Spring使用@Version注释的字段(如果它存在于实体中)来定义实体状态。通过重写 isNew(),我们强制 Spring 使用 @Id 字段,而乐观锁定机制本身继续照常工作。

我想,这对 JPA 也应该有帮助

© www.soinside.com 2019 - 2024. All rights reserved.