Hibernate Version Counter需要在刷新后刷新才能正确

时间:2015-08-18 16:55:41

标签: java hibernate jpa spring-data spring-data-jpa

所有

我们正在使用Hibernate 4.2.14.FinalHibernate JPA API 2.0Spring Data JPA 1.7.0.RELEASE。我们的交易通过JTA Container管理的交易进行管理。

我看到一个问题,如果子实体没有任何变化,子实体的版本计数器在save and flush之后错误地返回。但是,在实体上调用refresh会“修复”它。

举一个简单的例子来说明,假设我们有DepartmentEntityEmployeeEntity以及Department和Employee之间的一对多关系。

我们还有反映关系的DTO,因为我们不希望在我们的服务API中公开JPA注释的实体,所以我们也使用它们。

public class EmployeeEntity {
    ...
    @ManyToOne(cascade = {CascadeType.MERGE, CascadeType.REFRESH, CascadeType.PERSIST}, 
               optional = false)
    @JoinColumn(name = "DEPARTMENT_ID", nullable = false)
    private DepartmentEntity department;
    ...
}

我在Spring管理的Bean中有一个服务方法:

@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
public <EmployeeDTO> update(EmployeeDTO employee) {

    // Code here to retrieve the EmployeeEntity by Unique ID and copy props
    // from EmployeeDTO to EmployeeEntity, and also DepartmentDTO to 
    // DepartmentEntity.
    ... 

    // EmployeeRepository is a Spring Data JPA Repository 
    employeeEntity = employeeRepository.saveAndFlush(employeeEntity);

    // Convert EmployeeEntity back to EmployeeDTO and return it
    return newEmployeeDTOinstance;
}

如果我们开始:员工v1,部门v1,我们只更改了部门,会发生的事情是在saveAndFlush之后(通过调试器检查),我看到员工v2和部门v2。

然而,当整个事务完成并且我通过PL / SQL Developer检查数据库行时,Employee保持在版本1,而Department处于版本2。

下一次更新调用我传入了Employee v2和Department v2(因为这是JPA / Hibernate告诉我的最新版本)。但是,该数据库具有Employee版本1,并且我爆发了乐观锁定异常。

我可以通过在saveAndFlush之后调用refresh来“使其工作”,如下所示......

// EmployeeRepository is a Spring Data JPA Repository 
employeeEntity = employeeRepository.saveAndFlush(employeeEntity);

// Refresh after flush in order to ensure version numbers are correct on Entities.
employeeRepository.refresh(employeeEntity);

在Employee没有更改但部门没有更改的情况下,在saveAndFlush之后,我看到Employee v2,然后调用refresh将Employee设置回v1。

我的问题是 为什么? JPA / Hibernate假设通过在实体上调用saveAndFlush,版本计数器应该递增,但是在结束时事务看到没有更改,因此实际上没有更改数据库中的行?

有没有人曾经遇到过这个?任何见解或我可以看到的地方?

我确实读过这个Stackoverflow的回答,暗示了刷新后刷新https://stackoverflow.com/a/8137376/463196

然而,它没有解决版本计数器问题,而且似乎更多的是刷新通过数据库触发器进行的更改,因为我们让Hibernate管理版本计数器。

非常感谢你!

0 个答案:

没有答案