2010-11-26 7 views
21

He configurado para usar Hibernate secuencia de PostgreSQL (a través de anotaciones) para generar valores de clave de la columna principal Identificación de la siguiente manera:uso de hibernación de la secuencia de PostgreSQL no afecta a la tabla de secuencia

@Id 
@SequenceGenerator(name="pk_sequence",sequenceName="entity_id_seq") 
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="pk_sequence") 
@Column(name="id", unique=true, nullable=false) 
public int getId() { 
    return this.id; 
} 

Lo que veo con esta configuración es que de hibernación ya está asignando id valores> 3000 en persistente, mientras que la consulta en secuencia utilizada muestra los siguientes:

database=# select last_value from entity_id_seq; 
last_value 
------------ 
    69 

(1 ro w)

Preguntas:
¿Hay algún problema o no?
¿Debería hibernar la sincronización con la tabla de secuencia?
En caso negativo, ¿dónde almacena la última ID generada?

Gracias.

Respuesta

25

Tuve el mismo problema. Está relacionado con las estrategias de asignación de id de Hibernate. Cuando elija GenerationType.SEQUENCE, Hibernate utiliza la estrategia HiLo que asigna identificaciones en bloques de 50 de forma predeterminada. Por lo tanto se puede establecer de forma explícita allocationSize valor de la siguiente manera:

@Id 
@SequenceGenerator(name="pk_sequence",sequenceName="entity_id_seq", allocationSize=1) 
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="pk_sequence") 
@Column(name="id", unique=true, nullable=false) 
public int getId() { 
    return this.id; 
} 

Sin embargo, también he escuchado opiniones que el uso de la estrategia de Hilo con un allocationSize = 1 no es una buena práctica. Algunas personas recomiendan usar GenerationType.AUTO lugar cuando se tiene que hacer frente a las secuencias de bases de datos gestionados

Actualización: me terminan yendo con allocationSize = 1, y las cosas parecen funcionar como espero ahora. Mi aplicación es tal que realmente no necesito bloques de ID de todos modos, así que YMMV.

+0

¡gracias, hermano! Observé allocationSize desde el principio, pero pensé que se trata de número de invocaciones y asumí que la secuencia debería estar bien con cualquier valor. ¡Gracias de nuevo! – forker

+0

Supongo que esto lo hace Hibernate por motivos de rendimiento (menos viajes de ida y vuelta a la base de datos). Si experimenta contención en la secuencia en sí con un low allocationSize (llamadas slow nextval()), puede considerar establecer un caché para la secuencia en PostgreSQL –

20

NO UTILIZAR GenerationType.SEQUENCE para las secuencias de Postgres!

Es completamente contra-intuitivo, pero la gente de Hibernate se equivocó por completo. Usted debe usar GenerationType.AUTO o Hibernate demoler sus secuencias si tiene que reiniciar/reconstruir su base de datos. Es casi criminalmente negligente que permitan que este código entre en producción, pero el equipo de Hibernate es bastante famoso por sus posturas taimadas hacia posiciones completamente erróneas (verifique su posición en LEFT JOINs, por ejemplo).

+3

¡Buen punto, Matt! pero creo que hay una excusa para usar GenerationType.SEQUENCE: si tiene una tabla heredada de otra con el serial pk heredado, por lo tanto, compartiendo una secuencia para ella, GenerationType.AUTO no asignará un valor correcto para el serial pk (lo hará se ejecuta en un valor duplicado). – forker

+4

Estoy totalmente en desacuerdo. Simplemente debe especificar un 'SequenceGenerator' para ir con él, y (si desea interoperar con aplicaciones que no son de Hibernate) establezca el allocationSize en 1. En versiones más recientes puede usar' hibernate.id.new_generator_mappings = true' para restaurar cordura; Es posible que no haya sido así cuando escribiste esto, pero la opción allocationSize ciertamente sí. –

7

Primero, debe determinar qué versión de Hibernate está utilizando. En términos de versiones hibernate-core, 3.2 en adelante introdujo un soporte más consistente para los generadores de id especialmente en lo que respecta a lo definido en las anotaciones. Ver http://in.relation.to/Bloggers/New323HibernateIdentifierGenerators para una discusión.

Siguiente 3.6 introdujo una configuración ('hibernate.id.new_generator_mappings') que hace que los generadores discutidos en ese blog sean la manera predeterminada de manejar las anotaciones JPA. La configuración es falsa de forma predeterminada porque Hibernate tiene que mantener la compatibilidad con versiones anteriores. Si desea el nuevo comportamiento (que se recomienda por completo), simplemente configure esa configuración en verdadero.

El modo en que se maneja GenerationType depende de la versión que esté utilizando y de si tiene 'hibernate.id.new_generator_mappings' establecido en verdadero. Voy a suponer que está utilizando 3.6+ (ya que nada más vieja es, así, de edad) y tenemos conjunto '' hibernate.id.new_generator_mappings true (ya que esa es la recomendación para nuevas aplicaciones):

  1. GenerationType. AUTO -> tratados como GenerationType.SEQUENCE
  2. GenerationType.SEQUENCE -> mapas a la clase org.hibernate.id.enhanced.SequenceStyleGenerator discutido en el blog
  3. GenerationType.TABLE -> mapas a la org.hibernate.id. clase.TablaGenerator mejorado discutido en el blog
0

En Postgres I wo ULD hacer esto:

@Id 
@SequenceGenerator(name="pk_sequence",sequenceName="\"entity_id_seq\"") 
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="\"pk_sequence\"") 
@Column(name="\"id\"", unique=true) 
private int id; 

en su mayoría con nombres en mayúsculas necesita ser aprobada cotizaciones escapado a fin de comprender Postgres y encontrar las tablas, columnas o secuencias de nombres de hibernación.

Cuestiones relacionadas