hibernate sequence id-generation

hibernate - Hibernar con la secuencia de Oracle no lo usa



sequence id-generation (3)

He configurado hibernar para usar la secuencia de Oracle. La secuencia se crea con caché = 20, incremento = 1.

Todo funciona bien, hibernando entidades persistentes. El valor de id es extraño: 50,51 .... 76,201,202 ... 209,1008,1009,5129,5130 ...

Si pido un valor de secuencia (seleccione hibernate_sequence.nextval desde dual) obtengo un valor como 2,3,4 ...

Si activo la depuración de hibernate sql, es hora de llamar a la hora "seleccione hibernate_sequence.nextval desde dual", ¡pero el número asignado por hibernación a ID no se transmite en secuencia!

@Id @Column(name = "ID", insertable = false, updatable = false) @SequenceGenerator(name = "SequenceIdGenerator", sequenceName = "HIBERNATE_SEQUENCE") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SequenceIdGenerator") private Long id;


Esto se debe a que SequenceGenerator no es realmente un generador de secuencias. Es un generador de secuencia hi-lo. Esto significa que la primera vez que se invoca, obtiene el siguiente valor de la secuencia (6 por ejemplo), luego multiplica este valor por 50 y le da el resultado (300). La próxima vez que se invoca, devuelve 301 (sin ir a la secuencia), y así sucesivamente hasta que llega a 349. Luego le pide a la secuencia el siguiente valor y obtiene 7, que se multiplica por 50 nuevamente para darle 350. Mi La descripción del algoritmo podría estar desactivada por uno, pero entiendes la idea.

Si detiene e inicia su aplicación, tendrá brechas. Pero es más eficiente que un generador de secuencia pura porque solo realiza una llamada de base de datos una vez en 50 generaciones.

Consulte http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#mapping-declaration-id-enhanced-optimizers y http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#mapping-declaration-id-generator para más detalles.


Supongo que su pregunta es que los valores de la columna de ID en la base de datos no son una secuencia natural, pero por qué está viendo lagunas:

Un poco de fondo:

  • Cada vez que llama, select HIBERNATE_SEQUENCE.nextval from DUAL el valor de la secuencia aumenta.
  • Como su nombre de secuencia es genérico en lugar de específico a la tabla, si tiene varias entidades que utilizan HIBERNATE_SEQUENCE como generador de ID, los valores de las secuencias se usan en todas las entidades.
  • Si alguna otra aplicación utiliza HIBERNATE_SEQUENCE, el valor también se omite.
  • Mientras usa CACHE = 20, Oracle tomará los números de secuencia en bloques de 20 y luego usará un caché interno para devolver los números. Esto puede hacer que los números se omitan si se pierde el caché (por ejemplo, si se cierra el DB).
  • Si se eliminan filas de su base de datos, el valor de secuencia no cambia

Por ejemplo, considere el siguiente escenario:

Tienes dos entidades Entity1 y Entity2 utilizando HIBERNATE_SEQUENCE como generador de ID:

  1. El valor actual de HIBERNATE_SEQUENCE es 100
  2. Se inserta una Entidad1 (utiliza HIBERNATE_SEQUENCE que devuelve 101)
  3. Se inserta una Entidad2 (utiliza HIBERNATE_SEQUENCE que devuelve 102)
  4. Se inserta una Entidad2 (utiliza HIBERNATE_SEQUENCE que devuelve 103)
  5. La Entidad2 con ID 103 se borra
  6. Ejecuta manualmente select HIBERNATE_SEQUENCE.nextval from DUAL (devuelve 104)
  7. Se inserta una Entidad1 (utiliza HIBERNATE_SEQUENCE que devuelve 105)
  8. Se inserta una Entidad2 (utiliza HIBERNATE_SEQUENCE que devuelve 106)

Así que al final tendrás:

  • Entidad1 con identificaciones (101, 105)
  • Entidad2 con identificaciones (102, 106)

lo que explica las lagunas.

EDITAR:

Incluso si el @SequenceGenerator se configuró para usar el SequenceGenerator lugar del SequenceHiLoGenerator (como lo señaló JB Nizet, que creo que es una mejor explicación de las brechas), los vacíos en los ID generados por las secuencias son una ocurrencia común.


CREATE SEQUENCE SEQ_SEQUENCENAME INCREMENT BY 1 START WITH 1 MINVALUE 1; grant all on SEQ_SEQUENCENAME to public; @Id @Column(name = "ID", unique = true, nullable = false) @SequenceGenerator(name = "SequenceIdGenerator", sequenceName = "SEQ_SEQUENCENAME") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SequenceIdGenerator") private int Id;