que para objetos metodo implementar example comparar como java hibernate orm equals hashcode

java - para - ¿Cómo se deben implementar equals y hashcode al usar JPA e Hibernate?



metodo hash java (8)

¿Cómo deben implementarse los códigos equies y hashcode de la clase modelo en Hibernate? ¿Cuáles son los peligros comunes? ¿La implementación predeterminada es lo suficientemente buena para la mayoría de los casos? ¿Tiene algún sentido usar claves comerciales?

Me parece que es bastante difícil hacerlo funcionar correctamente en todas las situaciones, cuando se tienen en cuenta la recuperación diferida, la generación de id., El proxy, etc.


Cuando una entidad se carga a través de una carga diferida, no es una instancia del tipo base, sino que es un subtipo generado dinámicamente por javassist, por lo que una verificación en el mismo tipo de clase fallará, así que no use:

if (getClass() != that.getClass()) return false;

en su lugar use:

if (!(otherObject instanceof Unit)) return false;

que también es una buena práctica, como se explica en Implementando iguales en Prácticas de Java .

por la misma razón, acceder directamente a los campos, puede no funcionar y devolver nulo, en lugar del valor subyacente, por lo tanto, no use la comparación en las propiedades, pero use los captadores, ya que podrían desencadenar la carga de los valores subyacentes.


En la documentación de Hibernate 5.2, dice que es posible que no desee implementar hashCode e iguale en absoluto, según su situación.

https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#mapping-model-pojo-equalshashcode

En general, dos objetos cargados de la misma sesión serán iguales si son iguales en la base de datos (sin implementar hashCode e iguales).

Se complica si usa dos o más sesiones. En este caso, la igualdad de dos objetos depende de su implementación de método igual.

Además, te meterás en problemas si tu método equals está comparando identificaciones que solo se generan al persistir un objeto por primera vez. Puede que aún no estén allí cuando se llame a los iguales.


Hay un artículo muy bueno aquí: https://docs.jboss.org/hibernate/stable/core.old/reference/en/html/persistent-classes-equalshashcode.html

Citando una línea importante del artículo:

Recomendamos implementar equals () y hashCode () usando Business Key Equity. La igualdad de clave empresarial significa que el método equals () compara solo las propiedades que forman la clave de negocio, una clave que identificaría nuestra instancia en el mundo real (una clave candidata natural):

En lenguaje sencillo

public class Cat { ... public boolean equals(Object other) { //Basic test / class cast return this.catId==other.catId; } public int hashCode() { int result; return 3*this.catId; //any primenumber } }


La mejor implementación equals / hashCode es cuando usa una clave comercial única .

La clave comercial debe ser coherente en todas las transiciones de estado de la entidad (transitoria, adjunta, separada, eliminada), por eso no puede confiar en la id para la igualdad.

Otra opción es cambiar al uso de identificadores de UUID , asignados por la lógica de la aplicación. De esta forma, puede usar el UUID para equals / hashCode porque el ID se asigna antes de que la entidad se vacíe.

Incluso puede usar el identificador de entidad para equals y hashCode , pero eso requiere que siempre devuelva el mismo valor hashCode para asegurarse de que la entidad tenga el valor hCode coherente en todas las transiciones de estado de entidad. Echa un vistazo a esta publicación para obtener más información sobre este tema .


No creo que la respuesta aceptada sea precisa.

Para responder la pregunta original:

¿La implementación predeterminada es lo suficientemente buena para la mayoría de los casos?

La respuesta es sí, en la mayoría de los casos sí lo es.

Solo necesita reemplazar equals() y hashcode() si la entidad se usará en un Set (que es muy común) Y la entidad se desconectará de, y posteriormente se volverá a conectar a, hibernar sesiones (lo cual es un uso poco común) de hibernación).

La respuesta aceptada indica que los métodos deben ser anulados si cualquiera de las condiciones es verdadera.


Sí, es difícil. En mi proyecto equals y hashCode ambos dependen de la identificación del objeto. El problema de esta solución es que ninguno de ellos funciona si el objeto no se ha conservado aún, ya que la base de datos genera el id. En mi caso, eso es tolerable ya que en casi todos los casos los objetos se conservan de inmediato. Aparte de eso, funciona muy bien y es fácil de implementar.


Si superó a equals , asegúrese de cumplir sus contratos:

  • SIMETRÍA
  • REFLEXIVO
  • TRANSITIVO
  • CONSISTENTE
  • NON NULL

Y anula hashCode , ya que su contrato se basa en la implementación de equals a equals .

Joshua Bloch (diseñador de Collection framework) instó encarecidamente a que se siguieran estas reglas.

  • elemento 9: anule siempre hashCode cuando anula iguales

Hay un efecto involuntario grave cuando no se cumplen estos contratos. Por ejemplo, List.contains(Object o) puede devolver un valor boolean incorrecto ya que el contrato general no se cumple.


Hibernate tiene una bonita y larga descripción de cuándo / cómo anular equals() / hashCode() en la documentation

La esencia de esto es que solo debes preocuparte si tu entidad formará parte de un Set o si vas a separar / adjuntar sus instancias. Este último no es tan común. El primero generalmente se maneja mejor a través de:

  1. Basar equals() / hashCode() en una clave comercial, por ejemplo, una combinación única de atributos que no va a cambiar durante la vigencia del objeto (o, al menos, de la sesión).
  2. Si lo anterior es imposible, la base equals() / hashCode() en la clave primaria SI está establecida y la identidad del objeto / System.identityHashCode() caso contrario. La parte importante aquí es que necesita volver a cargar su Conjunto después de que se le haya agregado una nueva entidad y haya persistido; de lo contrario, puede terminar con un comportamiento extraño (lo que en última instancia puede dar como resultado errores y / o corrupción de datos) porque su entidad puede asignarse a un depósito que no coincide con su hashCode() actual.