sql >> Base de Datos >  >> RDS >> PostgreSQL

hibernate no pudo obtener el siguiente valor de secuencia

El dialecto PostgreSQL de Hibernate no es muy brillante. No sabe acerca de sus secuencias por SERIAL, y supone que hay una secuencia global en toda la base de datos llamada "hibernate_sequence" que puede usar.

(ACTUALIZAR :Parece que las versiones más recientes de Hibernate pueden usar las secuencias por tabla predeterminadas cuando GenerationType.IDENTITY está especificado. Pruebe su versión y use esta en lugar de la siguiente si funciona para usted).

Debe cambiar sus asignaciones para especificar explícitamente cada secuencia. Es molesto, repetitivo y sin sentido.

@Entity
@Table(name = "JUDGEMENTS")
public class Judgement implements Serializable, Cloneable {

    private static final long serialVersionUID = -7049957706738879274L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator="judgements_id_seq")
    @SequenceGenerator(name="judgements_id_seq", sequenceName="judgements_id_seq", allocationSize=1)
    @Column(name = "JUD_ID")
    private Long _judId;
...

El allocationSize=1 es bastante importante Si lo omite, Hibernate asumirá ciegamente que la secuencia está definida con INCREMENT 50 así que cuando obtiene un valor de una secuencia, puede usar ese valor y los 49 valores debajo de él como claves únicas generadas. Si las secuencias de su base de datos aumentan en 1, el valor predeterminado, esto dará como resultado violaciones únicas, ya que Hibernate intenta reutilizar las claves existentes.

Tenga en cuenta que obtener una clave a la vez podrá resultar en un viaje de ida y vuelta adicional por inserto. Por lo que sé, Hibernate no es capaz de usar INSERT ... RETURNING para devolver de manera eficiente las claves generadas, ni aparentemente puede usar la interfaz de claves generadas por JDBC. Si le dices que use una secuencia, llamará a nextval para obtener el valor entonces insert eso explícitamente, resultando en dos viajes de ida y vuelta. Para reducir el costo de eso, puede establecer un mayor incremento en las secuencias de teclas con muchas inserciones, recordando configurarlo en el mapeo y la secuencia de la base de datos subyacente. Eso hará que Hibernate llame a nextval con menos frecuencia y almacena en caché bloques de llaves para repartir a medida que avanza.

Estoy seguro de que puede ver en lo anterior que no estoy de acuerdo con las opciones de diseño de Hibernate hechas aquí, al menos desde la perspectiva de usarlo con PostgreSQL. Deberían estar usando getGeneratedKeys o usando INSERT ... RETURNING con DEFAULT para la clave, dejando que la base de datos se encargue de esto sin que Hibernate tenga que preocuparse por los nombres de las secuencias o el acceso explícito a ellas.

Por cierto, si está utilizando Hibernate con Pg, posiblemente también desee un disparador de bloqueo de operación para que Pg permita que el bloqueo optimista de Hibernate interactúe de manera segura con el bloqueo normal de la base de datos. Sin él o algo parecido, sus actualizaciones de Hibernate tenderán a aplastar los cambios realizados a través de otros clientes SQL regulares. Pregúntame cómo lo sé.