2010-01-28 35 views
21

Tengo Oracle db heredado con una secuencia llamada PRODUCT_ID_SEQ.¿Cómo usar la secuencia existente de Oracle para generar id en hibernación?

Aquí es el mapeo de Product clase para la que necesito generar identificadores correctos:

public class Product { 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, 
         generator = "retailerRaw_seq") 
    @SequenceGenerator(name = "retailerRaw_seq", 
         sequenceName = "PRODUCT_ID_SEQ") 
    private Long id; 

    ... 
} 

pero parece ids se generan con un intervalo de 50, como 1000, 1050, 1100 etc. Esto corresponde a la valor predeterminado de allocationSize propiedad = 50. Eso significa que Hibernate en realidad no usa la secuencia que ya está definida en el db.

¿Cómo hago que Hibernate use la secuencia?

+0

pregunta duplicado: Ver http://stackoverflow.com/questions/1729723/hibernate -does-not-generate-identifier-when-use-orracle-sequence/1729753 # 1729753 –

+2

No, no es un duplicado. Vea a continuación la respuesta – Tristan

Respuesta

17

No estoy acostumbrado a utilizar las anotaciones, esto es lo que tengo en mi * .hbm.xml:

<id name="id" type="java.lang.Integer"> 
    <column name="ID_PRODUCT" /> 
    <generator class="sequence-identity" > 
     <param name="sequence">PRODUCT_ID_SEQ</param> 
    </generator> 
</id> 

Puede asignar fácilmente a este anotaciones. El generador secuencia-identidad utiliza el incremento automático con secuencias.

+1

Esta es la forma correcta de hacerlo (con xml) vea a continuación un ejemplo con anotaciones – Tristan

+2

+1 y recuerde agregar ' true' en su 'hibernate.cfg.xml' archivo. – Withheld

0


De forma predeterminada, Hibernate utiliza el generador de secuencias HiLo que, a menos que tenga necesidades especiales, es bueno (en cuanto al rendimiento). Usted puede leer más de eso en mi blog here

Eyal

+0

¿Alguna idea de cambiar el algoritmo, diciendo agrupado en lugar de hilo utilizando anotaciones JPA? –

7

Aquí está un ejemplo de trabajo con anotaciones, de esta manera, se utilizará la secuencia de base de datos existente (también se puede utilizar la estrategia de "secuencia", pero con menor rendimiento en la inserción):

@Entity 
@Table(name = "USER") 
public class User { 

    // (...) 

    @GenericGenerator(name = "generator", strategy = "sequence-identity", parameters = @Parameter(name = "sequence", value = "USER_SEQ")) 
    @Id 
    @GeneratedValue(generator = "generator") 
    @Column(name = "ID", unique = true, nullable = false, precision = 22, scale = 0) 
    public Long getId() { 
     return this.id; 
    } 
+0

Encontré al usar esta técnica, funcionó, pero mi base de datos aumentaba el valor de su id en 2 en lugar de 1. ¿Alguna idea de por qué? – user898465

+0

verifique su definición de secuencia en Oracle, puede tener algo como "CREATE SEQUENCE mi_secuencia START CON 1 INCREMENTO POR 2" – Tristan

23

la respuesta a la pregunta original:

@SequenceGenerator(name="EL_SEQ", sequenceName="EL_SEQ",allocationSize=1) 

es allocationSize que establece el valor para incrementar por

+6

Votación máxima porque esta es una solución de JPA correcta en lugar de ser específica de Hibernate. Sin embargo, un allocationSize = 1 significa que se necesita obtener un número de la base de datos para cada inserción en lugar de almacenar en caché una gran cantidad de Id. A la vez, por lo que viene con una degradación de rendimiento muy pequeña. –

3

Si usa javax.persistence.SequenceGenerator, hibernate use hilo y posiblemente creará grandes lagunas en la secuencia. Hay un puesto de abordar este problema: https://forum.hibernate.org/viewtopic.php?t=973682

hay dos maneras de solucionar este problema

  1. En la anotación SequenceGenerator, añadir allocationSize = 1, initialValue = 1

  2. en lugar de utilizar javax .persistence.SequenceGenerator, utilice org.hibernate.annotations, así:

    @ javax.persistence.SequenceGenerator (name = "Question_id_sequence", sequenceName = "S_QUESTION")

    @ org.hibernate.annotations.GenericGenerator (name =, la estrategia = "secuencia" "Question_id_sequence", los parámetros = {@parameter (name = "secuencia", valor = "S_QUESTION")})

He probado ambas formas, lo cual funciona bien.

2

Utilizo el siguiente en PostgreSQL y funciona muy bien.

@Id 
@GeneratedValue(generator = "my_gen") 
@SequenceGenerator(name = "my_gen", sequenceName = "my_seq_in_db") 
private int userId; 
5

Cree su nombre de secuencia en Oracle, por ejemplo, contacts_seq. en su clase POJO. Defina la siguiente anotación para su secuencia.

@Id 
@GeneratedValue(strategy=GenerationType.AUTO, generator="my_seq_gen") 
@SequenceGenerator(name="my_seq_gen", sequenceName="contacts_seq") 
2

allocationSize y incrementBy son cosas completamente diferentes.

Hibernate es, por supuesto, utilizando su secuencia creada en DB pero dependiendo de allocationSize puede encontrar brecha en el valor generado.

por ejemplo- Que asuma valor de secuencia actual es el 5, incremento de 1 dB en, y allocationSize por defecto 50.

Ahora usted desea guardar una colección de 3 elemento a través de hibernación, entonces Hibernate asignará la identificación generada 250, 251, 252

Esto es para fines de optimización. Hibernate no tiene que regresar a db y obtener el siguiente valor incrementado.

Si no desea que esto sólo la creación de allocationSize = 1 como ya se ha contestado hará el propósito

3

que tenía el mismo problema al actualizar de 3.5.5 a 5.0.6.Final.

Lo resuelto por mapeo de re-configuración en el archivo de HBM:

<generator class="sequence"> 
     <param name="sequence">PRODUCT_ID_SEQ</param> 
    </generator> 

a:

<generator class="org.hibernate.id.enhanced.SequenceStyleGenerator"> 
     <param name="prefer_sequence_per_entity">true</param> 
     <param name="optimizer">none</param> 
     <param name="increment_size">1</param> 
     <param name="sequence_name">PRODUCT_ID_SEQ</param> 
    </generator> 
+0

¿Es necesario configurar increment_size en 1? ¿No es el valor predeterminado? –

Cuestiones relacionadas