所有,

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

I am seeing an issue where the version counter of a child entity is coming back incorrectly after a save and flush if there were no changes on the child entity. However, calling refresh on the entity "fixes" it.

举一个简单的例子来说明,假设我们有一个 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之后调用刷新来“使其工作”,如下所示......

// 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 .

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

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

我确实读过这个Stackoverflow的答案,暗示 refresh after flushhttps://stackoverflow.com/a/8137376/463196

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

非常感谢你提前!