所有,
我们正在使用 Hibernate 4.2.14.Final
, Hibernate JPA API 2.0
和 Spring 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.
举一个简单的例子来说明,假设我们有一个 DepartmentEntity
和 EmployeeEntity
以及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 flush :https://stackoverflow.com/a/8137376/463196
但是,它没有解决版本计数器问题,而且似乎更多的是刷新通过数据库触发器进行的更改,因为我们让Hibernate管理版本计数器 .
非常感谢你提前!