如何使用hibernate-jpa2.0抛出OptimisticLockException

时间:2012-05-31 09:33:43

标签: java jpa-2.0 jboss7.x optimistic-locking

我目前正在项目中进行乐观锁定管理。 我们使用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。即使合并之前在协议juste中包含的版本在我的DB中的版本之下。

我找到了原因。这是负责任的:

    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。 因此,如果我分离实体,那么一切都会起作用(我猜)但是我不想这样做(如果开发者忘记它就会出现错误的来源......)。

你有什么想法吗?

1 个答案:

答案 0 :(得分:1)

将帖子 可能的替代方案: 还没试过,你可以尝试一下:

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

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

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


(原始信息)

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

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

可能不适用于你