2011-09-07 14 views
13

yo golpean un problema al escribir pruebas para una aplicación de base de datos utilizando JPA2 y EclipseLink:¿Debería considerarse el campo id de una entidad JPA en equals y hashCode?

añado alguna entidad a una base de datos, recuperarlo más tarde y quieren compararlo con una instancia que tiene los valores que espero que confirmar que la adición funcionó como yo pretendía.

En primer lugar me escribió algo así como

assertEquals(expResult, dbResult); 

que fracasó, ya que en realidad no puedo saber el valor de id campo, que se genera por la base de datos y, por tanto, difiere de dbResultexpResult la que he creado con new y poblado manualmente

veo dos opciones:

  • O me quito el campo de idequals y hashCode de modo que la comparación sólo se basa en los "valores reales". Sin embargo, no sé si esto causa problemas en la base de datos o en otro lugar.

  • O escribo mis pruebas para verificar de forma explícita todos los campos excepto id manualmente.

¿Qué debo hacer?

Respuesta

14

Puede encontrar mucha controversia sobre este. Mi postura es que absolutamente no usa una clave primaria de base de datos para nada en su aplicación. Debería ser completamente invisible. Identifique sus objetos en su aplicación por alguna otra propiedad o combinación de propiedades.

En el frente de "operaciones de prueba de persistencia", lo que realmente desea es verificar que los campos se hayan guardado y cargado correctamente y que la clave principal haya recibido algún valor cuando la guardó. Esto probablemente no es un trabajo para el método de igualdad en absoluto.

+7

podría encontrar mucha controversia? Eso es optimista. – digitaljoel

1

Escribiría mi prueba para verificar explícitamente los campos. Para facilitar esto, antes de realizar la prueba assertEqual, estableceré la identificación del resultado esperado y real en el mismo valor predefinido y luego usaré el método de igualdad normal.

La eliminación de ID de iguales no es justificable, simplemente porque las pruebas son un poco difíciles. Está renunciando a los beneficios de rendimiento graves y también a la integridad del código.

+0

¿Cuáles son los problemas de rendimiento e integridad asociados con no considerar la identificación? ¿No sería lo mismo buscar un ID de la base de datos que usar 'Object # hashCode' en mis métodos' equals' y 'hashCode'? – soc

+0

Digamos que usted tiene entidades de proyecto. Debe enviar una lista de proyectos únicos desde su capa de servicio. Ahora existe la posibilidad de que un igual defectuoso considere dos registros únicos como el mismo registro. Tener ID reduce este problema. Además, la solución no es escalable, tenemos que actualizar nuestro método equals, si decidimos cambiar lo que hace que un objeto sea único. –

+0

Tener una identificación que se garantiza que es única es perfecta para hash. Estamos garantizados para evitar colisiones Hash. De lo contrario, la calidad del hash se convierte en una función de si consideramos todos los atributos que deberían ser únicos e ignoramos todos los atributos que no lo son. –

7

Del libro Hibernate in Action, se recomienda definir una clave de negocio y probar la igualdad en eso. Una clave de negocios es "una propiedad, o una combinación de propiedades, que es única para cada instancia con la misma identidad de base de datos". En otras áreas, dice que no use el ID como una de esas propiedades, y no use valores en las colecciones.

7

No es recomendable confiar en los Ids generados en la base de datos en su implementación equals y hashCode. Debe confiar en los atributos verdaderamente únicos/semi-únicos de sus clases al verificar la igualdad y al generar los valores del código hash. El Hibernate documentation tiene una página extensa que analiza esto, y los hechos en él son aplicables a más o menos cada proveedor de JPA.

La razón subyacente para el uso de claves de negocio más de los valores generados en su base de datos y equalshashCode aplicación es que el proveedor JPA debe emitir una realidad SELECT después de que persiste la entidad en la base de datos. Si se comparan los objetos utilizando la base de datos genera identificadores, a continuación, el resultado final será tener una prueba de igualdad que falla en los siguientes escenarios:

  • Si E1 y E2 son entidades de la clase E (que verifica la igualdad usando la base de datos generada IDS) , entonces si E1 y E2 serán iguales si aún no se han almacenado en la base de datos. Esto no es lo que desea, especialmente si desea almacenar E1 y E2 en algunos Set antes de la persistencia. Esto es peor si los atributos de E1 y E2 poseen valores diferentes; la implementación equals evitaría que dos entidades significativamente diferentes se agreguen a un Set, y la implementación hashCode le dará un tiempo de búsqueda O(n) cuando las entidades se buscan desde un HashMap usando la clave principal.
  • Si E1 es una entidad gestionada que se ha persistido, y E2 es una entidad que no se ha persistido, a continuación, la prueba de la igualdad consideraría que E1! = E2 en el escenario en el que todos los valores de atributo de E1 y E2 (excepto para los ID) son similares. Nuevamente, esto probablemente no es lo que desea, especialmente si desea evitar las entidades duplicadas en la base de datos que difieren solo en sus Ids generados en la base de datos. Por lo tanto,

Los equals y hashCode implementaciones deben utilizar claves de negocio, con el fin de mostrar un comportamiento coherente para ambas entidades y persistieron unpersisted.

Cuestiones relacionadas