我正在Hibernate中开发一个应用程序,我有这样的模型类:
public class Employee
{
private int ID;
private String name;
private Department department;
//other properties
//constructors, getters and setters
}
请注意,ID
不是用户填充的值,而是使用GenerationType.Identity
作为strategy
填充。
我还有另一个班级Department
如下:
public class Department
{
private int ID;
private String name;
private Set<Employee> employees; //this is actually a HashSet
//other implementations
}
ManyToOne
和Employee
之间存在Department
双向关系。
所以要向现有的Employee
添加新的Department
,我会执行以下操作
Department existingDepartment = ...;
Employee newEmployee = ...;
existingDepartment.addEmployee(newEmployee);
employee.setDepartent(existinDepartment);
session.save(newEmployee);
现在从概念上讲,如果两个Employee
对象具有相同的ID
,则它们是相同的。因此,equals()
类中的Employee
方法如下所示:
public boolean equals(Object o)
{
if(!(o instanceOf Employee))
{
return false;
}
Employee other = (Employee)o;
if(this.ID == o.etID())
{
return true;
}
return false;
}
现在的问题是,当我创建new Employee();
时,我没有ID
,因为它会在持久化时分配。所以,当我说
existingDepartment.addEmployee(newEmployee);
HashSet
对象的内部Department
实际上正在使用被破坏的equals()
方法[因为它使用成员变量来确定未正确初始化的相等]。 / p>
这似乎是一个非常基本的问题但是,我该如何解决?或者我设计的课程完全错了?或者我应该重新编写equals
方法来比较其他值而不是ID
,我认为这是荒谬的。
答案 0 :(得分:6)
这似乎是一个非常基本的问题但是,我该如何解决?或者我 设计我的课完全错了?或者我的平等方法应该是 重写以比较其他值而不是ID,我想这会 是荒谬的。
对此有两种不同的理念。
a)基于DB id的equals()/ hashCode()
缺点:您无法比较持久对象和非持久对象
b)基于内容的equals()/ hashCode()
缺点:具有相同id的两个对象可能会变得不相等。
我更喜欢第二种方法,从Java的角度来看它更有意义(虽然不可能从数据库的角度来看)。 我唯一想确定的是你从不混淆方法。
之前已多次讨论过,顺便说一下:
答案 1 :(得分:1)
当o
为空时,重写你的equals方法,使其返回false:
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Employee other = (Employee) obj;
if (this.id != other.id && (this.id == null || !this.id.equals(other.id))) {
return false;
}
return true;
}
答案 2 :(得分:0)
在休眠中,通常可以告诉它在未保存到db时使用值。例如,我使用-1
作为尚未存储的ID。
您应该像这样初始化您的ID,以确保您获得一致的行为。
private int ID = -1;
答案 3 :(得分:0)
您可以添加具有不同非持久性ID的瞬态字段。 (也许你应该升级到“长”id)。 例如
这样的东西public class Employee {
private static int lastTID = 0;
private int ID = -1;
private transient int tID;
..
public Employee () {
synchronized (getClass()) {
tId = -- lastTID;
}
}
public boolean equals(Object o) {
..
Employee other = (Employee)o;
..
if (ID != -1) {
return ID == other.ID;
} else {
return other.ID == -1 && tID == other.tID;
}
}
在任何情况下,您都必须确保没有正在使用的已保存和未保存的员工。
另一个策略是首先保存Employee,然后将其添加到Department