Cómo elegir la estrategia de generación de id al usar JPA e Hibernate

102

Estaba revisando la sección de generación de Id de la guía de referencia de Hibernate y "persistencia de Java con Hibernate"

Hay bastantes opciones disponibles con Hibernate y JPA combinados.

Estaba buscando más documentación sobre cómo elegir la estrategia de generación de identificación específica.

También estoy buscando puntos de inflexión.

Por ejemplo, se espera que la estrategia de hilo reduzca la contención. Supongo que debe haber una compensación asociada con esta elección.

Quiero que me eduquen sobre las compensaciones.

¿Hay literatura disponible?

Vlad Mihalcea
fuente

Respuestas:

92

El API Doc es muy claro en esto.

Todos los generadores implementan la interfaz org.hibernate.id.IdentifierGenerator. Esta es una interfaz muy simple. Algunas aplicaciones pueden optar por proporcionar sus propias implementaciones especializadas, sin embargo, Hibernate proporciona una gama de implementaciones integradas. Los nombres de los accesos directos para los generadores integrados son los siguientes:

incremento

genera identificadores de tipo long, short o int que son únicos solo cuando ningún otro proceso está insertando datos en la misma tabla. No lo use en un clúster.

identidad

admite columnas de identidad en DB2, MySQL, MS SQL Server, Sybase y HypersonicSQL. El identificador devuelto es de tipo long, short o int.

secuencia

utiliza una secuencia en DB2, PostgreSQL, Oracle, SAP DB, McKoi o un generador en Interbase. El identificador devuelto es de tipo long, short o int

hilo

utiliza un algoritmo hi / lo para generar eficientemente identificadores de tipo long, short o int, dada una tabla y columna (por defecto hibernate_unique_key y next_hi respectivamente) como fuente de valores hi. El algoritmo hi / lo genera identificadores que son únicos solo para una base de datos en particular.

seqhilo

utiliza un algoritmo hi / lo para generar de manera eficiente identificadores de tipo long, short o int, dada una secuencia de base de datos con nombre.

uuid

utiliza un algoritmo UUID de 128 bits para generar identificadores de tipo cadena que son únicos dentro de una red (se utiliza la dirección IP). El UUID está codificado como una cadena de 32 dígitos hexadecimales de longitud.

guid

utiliza una cadena GUID generada por la base de datos en MS SQL Server y MySQL.

nativo

selecciona identidad, secuencia o hilo dependiendo de las capacidades de la base de datos subyacente.

asignado

permite que la aplicación asigne un identificador al objeto antes de que se llame a save (). Esta es la estrategia predeterminada si no se especifica ningún elemento.

Seleccione

recupera una clave primaria, asignada por un disparador de la base de datos, seleccionando la fila por alguna clave única y recuperando el valor de la clave primaria.

exterior

utiliza el identificador de otro objeto asociado. Por lo general, se usa junto con una asociación de clave primaria.

identidad de secuencia

una estrategia de generación de secuencia especializada que utiliza una secuencia de base de datos para la generación de valor real, pero combina esto con JDBC3 getGeneratedKeys para devolver el valor de identificador generado como parte de la ejecución de la instrucción de inserción. Esta estrategia solo es compatible con los controladores Oracle 10g destinados a JDK 1.4. Los comentarios sobre estas declaraciones de inserción están deshabilitados debido a un error en los controladores de Oracle.

Si está construyendo una aplicación simple con pocos usuarios concurrentes, puede optar por incremento, identidad, hilo, etc. Estos son simples de configurar y no necesitan mucha codificación dentro de la base de datos.

Debe elegir secuencia o guid según su base de datos. Estos son seguros y mejores porque la idgeneración ocurrirá dentro de la base de datos.

Actualización: Recientemente tuvimos un problema con la identidad en el que el tipo primitivo (int) se solucionó usando el tipo warapper (Integer) en su lugar.

ManuPK
fuente
Muchas gracias por su respuesta. Ya he mirado los documentos. Sin embargo, estoy buscando por qué la gente usaría algo como hilo y seqhilo. ¿Cuándo tomamos esa decisión? ¿Cuáles son los casos de uso para select.
Cuando hay algo tan sencillo como una secuencia o una guía, lo que puede requerir que el desarrollador elija otras vías.
1
He actualizado mi respuesta. En realidad , el incremento, la identidad, el hilo, etc. son más simples. pero no son adecuados para aplicaciones empresariales. Mantener todas las opciones no es un problema, ¡pero asegúrese de utilizar la más adecuada para usted!
ManuPK
Si. Hasta ahora no tuve el privilegio de votar a favor o aceptar.
Estoy buscando sumergirme en más detalles, si tiene tiempo, hágamelo saber.
45

Básicamente, tiene dos opciones principales:

  • Puede generar el identificador usted mismo, en cuyo caso puede utilizar un identificador asignado .
  • Puede usar la @GeneratedValueanotación e Hibernate le asignará el identificador.

Para los identificadores generados tiene dos opciones:

Para los identificadores numéricos tiene tres opciones :

  • IDENTIDAD
  • SECUENCIA
  • MESA

IDENTITY es solo una buena opción cuando no puede usar SEQUENCE (por ejemplo, MySQL) porque deshabilita las actualizaciones por lotes de JDBC .

SEQUENCE es la opción preferida, especialmente cuando se usa con un optimizador de identificador como pooled o pooled-lo .

TABLE debe evitarse a toda costa, ya que utiliza una transacción separada para recuperar el identificador y los bloqueos de nivel de fila que escalan mal.

Vlad Mihalcea
fuente
20


Hace un tiempo escribí un artículo detallado sobre los generadores de claves de Hibernate: http://blog.eyallupu.com/2011/01/hibernatejpa-identity-generators.html

Elegir el generador correcto es una tarea complicada, pero es importante intentar hacerlo bien lo antes posible; una migración tardía puede ser una pesadilla.

Un poco fuera de tema, pero una buena oportunidad para plantear un punto que generalmente se pasa por alto y es compartir claves entre aplicaciones (a través de API). Personalmente, siempre prefiero las claves sustitutas y si necesito comunicar mis objetos con otros sistemas, no expongo mi clave (aunque sea una sustituta), utilizo una 'clave externa' adicional. Como consultor, he visto más de una vez 'grandes' integraciones de sistemas usando claves de objeto (el enfoque de 'está ahí, usémoslo') solo para encontrar uno o dos años más tarde que un lado tiene problemas con el rango de claves o algo así del tipo que requiere una migración profunda en el sistema exponiendo sus claves internas. Exponer su clave significa exponer un aspecto fundamental de su código a restricciones externas a las que realmente no debería exponerse.

Eyal Lupu
fuente
2

Encuentro muy valiosa esta conferencia https://vimeo.com/190275665 , en el punto 3 se resumen estos generadores y también da un análisis de rendimiento y una pauta cuando usas cada uno.

Adelin
fuente
6
Ese video parece muy familiar.
Vlad Mihalcea