Por defecto, todos los objetos en Java heredan de la case Object los métodos hashCode y equals los cuales sirvan para identificar si dos variables hacen referencia al mismo objeto.
El comportamiento de facto del método hashCode retorna la posición en memoria de un objeto, y el método equals compara el hashCode de los dos objetos evaluados, de esta forma, si las dos variables hacen referencia a la misma posición de memoria, entonces se dice que son igual, de lo contrario son diferentes.
En el caso de las Entidades, la implementación default de estos métodos no funciona correctamente, debido a que una Entidad de dice que es igual a otra si se cumplen dos condiciones:
• Los dos objetos son de la misma clase.
• El valor de su ID (@Id) son iguales
Si estas dos condiciones se cumplen entonces las dos entidades son iguales sin importar que no hagan referencia a mismo objeto en memoria. Debido a esto, es que es importante sobrescribir estos dos métodos para que evalúen a una Entidad por las dos condiciones mencionadas.
Implementando los métodos hashCode & equals
Algo que me ha llamado mucho la atención es que a pesar de que estos dos métodos son básicos y que se utilizan con regularidad, muchas personas no entienden como trabajan internamente y aún menos como sobrescribirlos correctamente, si eres una de esas personas, no te preocupes ya que los IDE’s ya tiene por default utilidades que nos ayudan a generarlos de forma adecuada.
Lo primero que haremos será abrir la entidad Employee que hemos venido trabajando a lo largo de este tutorial. Luego presionaremos Source > Insert Code del menú principal, esto arrojara una pequeña lista de acciones, seleccionamos la opción equals() and hashCode(). Nos arrojara una pantalla como la siguiente:
En esta pantalla debemos todos los campos que conformen el ID de la Entidad, en este caso solo sería el atributo ID, lo seleccionamos en las dos listas como aparece en la imagen anterior, y presionamos generate. Esto concluirá la generación de los dos métodos y se deberán de ver así:
package com.obb.jpa.jpaturorial.entity; import java.util.Objects; import javax.persistence.*; /** * @author Oscar Blancarte */ @Entity @Table( name = "EMPLOYEES" , schema = "jpatutorial", indexes = {@Index(name = "name_index", columnList = "name",unique = true)} ) public class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY, generator = "EmployeeTable") private Long id; private String name; @Override public int hashCode() { int hash = 7; hash = 29 * hash + Objects.hashCode(this.id); return hash; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Employee other = (Employee) obj; if (!Objects.equals(this.id, other.id)) { return false; } return true; } /** * GETs and SETs */ }
El método hashCode regresará un hash generado a partir del ID, veamos que en la ecuación interviene un variable hash con valor 7. No te preocupes por eso, es solo un número generado al azar.
Tambíen los quiero invitar a ver mi curso de JPA, donde explico todos estos temas aplicados con API REST, https://codmind.com/courses/jpa
Por otra parte el método equals lo primero que hará será comparar los dos objetos con el operador ==, este operador se traduce en la llamada del método hashCode de tal manera que this == obj sería igual a this.hashCode() == obj.hashCode(), y como va vimos el hashCode se genera a partir del ID y no a la posición de memoria, por tal motivo la expresión solo sería verdadera en caso de ambos objetos tengan el mismo ID.
NOTA: Este artículo es solo una sección del Tutorial de JPA, para ver el contenido completo de este tutorial regresa al Índice en el botón de abajo.