0

我目前正在我的项目中进行乐观锁定管理。我们使用 JPA 2.0 (hibernate-jpa2.0-api-1.0.1.Final),数据源由 JBoss 7 提供。

我做了什么

在我的实体“AccordSimple”中,我使用@Version 注释:

@Entity
@Table(name = "AccordSimple")
public class AccordSimple {
    @Id
    @SequenceGenerator(name = "parametresubsidesequence", 
        sequenceName = "parametresubsidesequence", allocationSize = 1)  
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "parametresubsidesequence")
    private Long id;

    // Optimistic lock.
    @Version
    private Long version;

}

这是我的 AccordServiceImpl

public AccordDTO updateAccord(AccordDTO accordDTO) throws AppException {

    AccordSimple accord = getAccordRepository().findByReference(
            accordDTO.getAccordReference());

    if (accord == null) {
        return null;
    }

    // copy new values from the DTO...
    accord.setVariable(accordDTO.getVariable());
    // ... 

    // Set the version from the DTO (old version if someone changes before me!)
    accord.setVersion(accordDTO.getVersion());

    getAccordRepository().merge(accord);
    return accordDTO;
}

这样,不会抛出 OptimisticLockException。即使合并前一致的版本包含在我的数据库中的版本之下。

我已经找到了原因。这是负责人:

    AccordSimple accord = getAccordRepository().findByReference(
            accordDTO.getAccordReference()); 

因为如果我将方法更改为:

public AccordDTO updateAccord(AccordDTO accordDTO) throws AppException {

    AccordSimple accord = new AccordSimple(accordDTO.getAccordReference(), accordDTO.getVersion());

    // copy new values from the DTO...
    accord.setVariable(accordDTO.getVariable());
    // ... 

    // Set the version from the DTO (old version if someone changes before me!)
    accord.setVersion(accordDTO.getVersion());

    getAccordRepository().merge(accord);
    return accordDTO;
}

将抛出 OptimisticLockException!

问题

该版本来自 Hibernate 缓存,而不是来自我的 DTO。因此,如果我分离实体,那么一切都会正常工作(我猜),但我不想这样做(如果开发人员忘记它,则会出现错误的来源......)。

你有什么想法吗?

4

1 回答 1

1

[已编辑] 一种可能的选择:尚未尝试过,您可以尝试一下:

通过使用 @PostLoad 或带有 insertable=false,updateable=false 的额外列映射,在实体中保留一个额外的版本号。

让@PreUpdate 方法检查版本字段和额外版本字段。如果它们不匹配,则抛出异常。

所有这些都可以放在基础模型类中。所以没有人会忘记将逻辑放在实体中:)


(原始信息)

这正是我在之前的项目中所面临的。在执行乐观锁验证时,Hibernate 不会查看实体中的版本字段。

我解决那个时间的方法是在将 DTO“合并”到实体时验证自己。那时,我有一个实用程序来映射 DTO 和实体之间的属性。版本检查只是 DTO 中版本字段中的一个额外注释,而不是将值设置为相应实体的属性,当它不匹配时我会抛出异常。

不过可能不适用于你


于 2012-05-31T09:51:24.850 回答