Hiberate 实体等价和等同
Hiberate 实体等价和等同
在我们的应用中,很多时候我们都面临着这样的情况,我们必须比较两个对象以检查它们的相等性以满足某些业务规则。 在核心 Java 中,我们已经掌握了检查对象是否相等的知识,但是在 Hiberate 下,我们还需要注意一些额外的事情。 让我们了解一下那些额外的概念。
我们已经了解了 Hiberate 实体在其生命周期中的各种状态。 在那里,我们讨论了 Hiberate 大多数仅适用于持久对象。 众所周知,当我们在 hibernate 中有一个持久对象时,该对象代表了两个:
- 特定 Java 虚拟机(JVM)中类的实例
- 数据库表中的一行(或多行)
我们对第一个概念了解足够。 我将集中讨论第二点。
从同一会话中获取的对象
从同一 Hibernate 会话再次请求持久对象会返回类的相同 Java 实例,这意味着您可以使用标准 Java ==
等式语法比较这些对象。
让我们看一个简单的例子:
public static void main(String[] args)
{
Session sessionOne = HibernateUtil.getSessionFactory().openSession();
sessionOne.beginTransaction();
// Create new Employee object
EmployeeEntity emp = new EmployeeEntity();
emp.setFirstName("Lokesh");
emp.setLastName("Gupta");
//Save employee
sessionOne.save(emp);
sessionOne.getTransaction().commit();
//Get employee id
Integer genEmpId = emp.getEmployeeId();
//New session where we will fetch the employee two times and compare the objects
Session sessionTwo = HibernateUtil.getSessionFactory().openSession();
sessionTwo.beginTransaction();
EmployeeEntity employeeObj1 = (EmployeeEntity) sessionTwo.get(EmployeeEntity.class, genEmpId);
EmployeeEntity employeeObj2 = (EmployeeEntity) sessionTwo.get(EmployeeEntity.class, genEmpId);
//Checking equality
System.out.println(employeeObj1 == employeeObj2);
HibernateUtil.shutdown();
}
Output:
true
您可以在上面看到,我们在EmployeeEntity
上有两个实例,并且它们实际上都是同一个 Java 对象实例。
从不同会话中获取的对象
如果您从多个会话中向请求一个持久对象,则 Hibernate 将为每个会话提供不同的实例,如果您比较这些对象实例,则==
运算符将返回false
。
让我们比较上面示例中的实例“emp
”和“employeeObj1
”,结果将为假; 因为两者都是在单独的会话中获取的。
System.out.println(emp == employeeObj1);
System.out.println(emp.equals(employeeObj1));
Output:
false
false
因此,如果要在两个不同的会话中比较对象,则需要在 Java 持久化对象上实现equals()
方法,无论如何,您都应该经常执行此方法。 (请不要忘记将hashCode()
与它一起覆盖。)
阅读更多信息:覆盖
hashCode()
和equals()
方法
Hibernate 将实际对象包装在代理中,因此请始终在内部使用设置器方法而不是实际属性进行比较。
现在,根据建议添加equals()
方法,然后在检查EmployeeEntity
上两个实例的相等性时查看行为更改。
@Entity
@Table(name = "Employee")
public class EmployeeEntity implements Serializable
{
private static final long serialVersionUID = -1798070786993154676L;
@Id
@Column(name = "ID", unique = true, nullable = false)
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Integer employeeId;
@Column(name = "FIRST_NAME", unique = false, nullable = false, length = 100)
private String firstName;
@Column(name = "LAST_NAME", unique = false, nullable = false, length = 100)
private String lastName;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof EmployeeEntity)) return false;
EmployeeEntity otherEmployee = (EmployeeEntity) o;
if (getEmployeeId() != null ?
!getEmployeeId().equals(otherEmployee.getEmployeeId()) : otherEmployee.getEmployeeId() != null)
return false;
if (getFirstName() != null ?
!getFirstName().equals(otherEmployee.getFirstName()) : otherEmployee.getFirstName() != null)
return false;
if (getLastName() != null ?
!getLastName().equals(otherEmployee.getLastName()) : otherEmployee.getLastName() != null)
return false;
return true;
}
@Override
public int hashCode() {
int result = getEmployeeId() != null ? getEmployeeId().hashCode() : 0;
result = 31 * result + (getFirstName() != null ? getFirstName().hashCode() : 0);
result = 31 * result + (getLastName() != null?getLastName().hashCode() : 0);
return result;
}
//Setters and Getters
}
现在,使用equals()
方法再次检查是否相等。 (==
将返回false
,我们知道)。
System.out.println(emp.equals(employeeObj1));
Output:
true
现在,两个对象在逻辑上和程序上都是相等的。
项目要点
- 从相同的 Hibernate 会话再次请求持久对象将返回类的“相同 Java 实例”。
- 从不同的 Hibernate 会话中请求一个持久对象,将返回一个类的“不同的 Java 实例”。
- 最佳实践是,始终在 Hiberate 实体中实现
equals()
和hashCode()
方法; 并始终仅使用equals()
方法进行比较。