我并不期待这种行为,也不确定这是一个错误还是设计错误。
我们有一个带有子对象列表的父对象。它是使用连接表的单向关系。如果客户端请求父对象合并,则Hibernate 会增加父对象的版本,即使它的所有细节都没有更改。我不希望父对象版本改变,因为从逻辑上讲,父对象完全相同。有人有解释吗?
注1:由于集合在flush中被标记为脏,但如果集合为空或父对象不包含集合,则不会发生这种情况
p>注2:非常类似https://hibernate.atlassian.net/browse/HHH-3007由于不活动而自动关闭
注3:使用Hibernate 4.3.7.Final,但在Hibernate 3中测试了相同的行为
测试重现
@Test
public void testCreateAndUpdate() throws Exception {
// POST from client - note: deptartment object containing a single empty employee
String jsonFromClient = "{\"employees\":[{}]}";
Department department = mapper.readValue(jsonFromClient, Department.class);
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.persist(department);
tx.commit();
// simulates sending it back to client
String jsonToClient = mapper.writeValueAsString(department);
System.out.println(jsonToClient); // {"id":1,"version":0,"employees":[{"id":1,"version":0}]}
// PUT from client, but nothing has actually changed
jsonFromClient = jsonToClient;
department = mapper.readValue(jsonFromClient, Department.class);
// new session emulates the client updating the Department
session = sessionFactory.openSession();
tx = session.beginTransaction();
department = (Department) session.merge(department);
tx.commit();
// NOTE: PARENT VERSION INCREMENTED!!
jsonToClient = mapper.writeValueAsString(department);
System.out.println(jsonToClient); // {"id":1,"version":1,"employees":[{"id":1,"version":0}]}
}
Department.java
@Entity
public class Department {
private Long id;
private Long version;
private List<Employee> employees = new ArrayList<>();
@Id
@GeneratedValue
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
@Version
public Long getVersion() { return version; }
public void setVersion(Long version) { this.version = version; }
@OneToMany(cascade = CascadeType.ALL)
@JoinTable(name="DEPARTMENT_EMPLOYEE", joinColumns = @JoinColumn( name="DEPARTMENT_ID"), inverseJoinColumns = @JoinColumn( name="EMPLOYEE_ID"))
public List<Employee> getEmployees() { return employees; }
public void setEmployees(List<Employee> employees) { this.employees = employees; }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Department)) return false;
Department that = (Department) o;
//if (employees != null ? !employees.equals(that.employees) : that.employees != null) return false;
if (!id.equals(that.id)) return false;
if (!version.equals(that.version)) return false;
return true;
}
@Override
public int hashCode() {
int result = id.hashCode();
result = 31 * result + version.hashCode();
result = 31 * result + (employees != null ? employees.hashCode() : 0);
return result;
}
}
Employee.java
@Entity
public class Employee {
private Long id;
private Long version;
@Id
@GeneratedValue
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
@Version
public Long getVersion() { return version; }
public void setVersion(Long version) { this.version = version; }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Employee)) return false;
Employee employee = (Employee) o;
if (!id.equals(employee.id)) return false;
if (!version.equals(employee.version)) return false;
return true;
}
@Override
public int hashCode() {
int result = id.hashCode();
result = 31 * result + version.hashCode();
return result;
}
}