para english java database hibernate jpa orm

java - english - Tipo de caja vs primitivo como identificador de entidad



orm java (6)

En JPA (implementación de Hibernate) ¿Qué tipo es mejor usar como id de entidad: tipo en caja (por ejemplo, Integer ) o tipo sin caja (por ejemplo, int )?

Un amigo dijo que deberías usar tipos en caja porque cuando creas una nueva entidad en tu programa, Hibernate ve que la identificación es null y entiende que debería crear una nueva fila en la base de datos (en cambio, si id no es null Hibernate puede actualizar una fila existente en la base de datos).

Pero el identificador de mis entidades era int y funcionó bien sin ningún error, y sabemos que el valor predeterminado de las variables de instancia primitivas es 0 . Entonces dijo que tal vez la hibernación trata el 0 como especial y asume que el objeto es nuevo.


Bueno, usamos no primitivos y tenemos una razón fuerte para ello. Muchos de nuestros campos que son int/Integer por ejemplo, tienen un valor comercial absoluto de zero para ser perfectamente válidos. Piense en un campo de deuda, por ejemplo, está más que bien si el campo es zero , lo que significa que no tiene deuda.

El problema es que con primitivas, cero es un valor predeterminado, por lo que podría olvidarse de establecerlo, por ejemplo, a través de un setDebt , por lo que podría llegar a su base de datos con un valor que nunca tuvo la intención de ir allí. Por esta razón, usamos Integer con algunas validaciones que nunca deben ser nulas, por ejemplo; pero incluso si olvidamos agregar las validaciones adecuadas, ese código se romperá potencialmente con una excepción NullPointerException (preferiblemente en pruebas) y me gusta una excepción más que los valores inconsistentes en la base de datos.


Los identificadores únicos de entidades y colecciones pueden ser de cualquier tipo básico excepto binary, blob y clob. (Los identificadores compuestos también están permitidos, ver más abajo).

Los tipos de valores básicos tienen constantes de Tipo correspondientes definidas en org.hibernate.Hibernate. Por ejemplo, Hibernate.STRING representa el tipo de cadena.


No hay diferencia entre la primitiva (por ejemplo, int) y su envoltura (por ejemplo, Integer) para la identificación de la entidad. Ambos son válidos de acuerdo con la especificación JPA. El proveedor de JPA es lo suficientemente inteligente como para rastrear el estado y el ciclo de vida de una entidad. Cuando la identificación de la entidad es 0 (tipo primitivo) o NULL (tipo de envoltura), el proveedor JPA generará una identificación para la entidad si el generador de identificación está configurado. Cero no se considera como una identificación de entidad válida si la identificación se genera automáticamente.

Cmobilecom JPA ambos casos con Cmobilecom JPA y funciona igual de bien. Por supuesto, no se puede notar diferencia de rendimiento.

Descargo de responsabilidad: soy un desarrollador de Cmobilecom JPA , una implementación ligera de JPA para Java y Android.


Parece que la documentación actual recomienda utilizar el tipo de caja.

Le recomendamos que declare atributos de identificador de nombre consistente en clases persistentes y que use un tipo que pueda ser anulado (es decir, no primitivo).


Podemos pensar de esta manera:

Cuando tenemos un valor x :: Int , entonces ''x'' es un cálculo que cuando se evalúa devolverá un Int o estará en la parte inferior (indefinido).

Cuando se ejecuta el programa y se evalúa x , suponga que se evalúa como un Int real (no inferior). Luego, en el futuro, en cualquier momento en que se evalúe x, en lugar de rehacer todo el cálculo, solo queremos obtener el valor que calculamos anteriormente.

Lo que hacemos para lograr esto es reemplazar a thunk (cálculo) que calcula x con un thunk que simplemente devuelve el valor que se calculó anteriormente.

El problema es que cada vez que necesite obtener x en el futuro, deberá seguir este puntero hasta el código (trivial) que devuelve un valor. Esto se vuelve caro si necesita estos valores con frecuencia.

Introduzca valores sin caja. Un valor sin caja es solo ese valor de bajo nivel, no encerrado dentro de un procesador. Esto significa que es estricto en el sentido de que no puede ser indefinido sin que su programa muera necesariamente.


Prefiero el tipo de caja en el modelo de entidad porque eso da flexibilidad para usar el tipo de caja en los genéricos. Por ejemplo, aquí el modelo de entidad solo puede tener el tipo que se extiende a Serializable para id. Será útil más adelante en la capa de servicio donde podemos realizar varias operaciones en la clave principal.

public interface BaseEntity<E extends Serializable> extends Serializable { E getId(); }

El modelo de entidad podría ser como:

@Entity public class PhoneNumber implements BaseEntity<Long> { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "PHONE_NUMBER_ID") private Long id;