2010-01-28 15 views
21

Ho legacy Oracle db con una sequenza denominata PRODUCT_ID_SEQ.Come utilizzare la sequenza Oracle esistente per generare l'id in modalità di sospensione?

Ecco la mappatura dei Product classe per la quale ho bisogno di generare gli ID corretti:

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

    ... 
} 

ma sembra che gli ID vengono generati con un intervallo di 50, come 1000, 1050, 1100 ecc Questo corrisponde al valore predefinito della proprietà allocationSize = 50. Ciò significa che Hibernate non utilizza effettivamente la sequenza già definita nel db.

Come si fa in modo che Hibernate usi la sequenza?

+0

domanda Duplicate: Vedere http://stackoverflow.com/questions/1729723/hibernate -does-not-generate-identifier-when-using-oracle-sequence/1729753 # 1729753 –

+2

No, non è un duplicato. Vedi sotto per la risposta – Tristan

risposta

17

Io non sono abituato a utilizzare le annotazioni, questo è quello che ho nel mio * .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> 

Si può facilmente mappare questo per le annotazioni. Il generatore sequenza-identità utilizza l'incremento automatico con sequenze.

+1

Questo è il modo giusto per farlo (con xml) vedi sotto per un esempio con annotazioni – Tristan

+2

+1 e ricorda di aggiungere ' true' nel tuo File 'hibernate.cfg.xml'. – Withheld

0


Per impostazione predefinita, Hibernate utilizza il generatore HiLo di sequenza che, a meno che non si abbiano esigenze particolari, è buono (prestazioni). Si può leggere di più su che nel mio blog here

Eyal

+0

Qualche idea per cambiare algoritmo, dicendo di raggruppare invece di hilo usando le annotazioni JPA? –

7

Ecco un esempio di lavoro con le annotazioni, in questo modo, verrà utilizzata la sequenza di DB esistente (è anche possibile utilizzare la strategia di "sequenza", ma con meno prestazioni su inserimento):

@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

Ho trovato quando ho usato questa tecnica ha funzionato, ma il mio database stava incrementando il suo valore di id di 2 invece di 1. Qualche idea perché? – user898465

+0

controlla la tua definizione di sequenza in Oracle, potresti avere qualcosa come "CREATE SEQUENCE my_sequence START WITH 1 INCREMENT BY 2" – Tristan

23

la risposta alla domanda iniziale:

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

è allocationSize che imposta il valore da incrementare di.

+6

Upvoted perché questa è una soluzione JPA corretta invece di essere specifica di Hibernate. Tuttavia, allocazione = 1 significa che è necessario ottenere un numero dal database per ogni inserto piuttosto che memorizzare nella cache molti ID contemporaneamente, quindi si ha un degrado delle prestazioni molto piccolo. –

3

Se si utilizza javax.persistence.SequenceGenerator, l'ibernazione utilizza hilo e probabilmente creerà grandi spazi nella sequenza. C'è un post affrontare questo problema: https://forum.hibernate.org/viewtopic.php?t=973682

ci sono due modi per risolvere questo problema

  1. Nel annotazioni SequenceGenerator, aggiungere allocationSize = 1, initialValue = 1

  2. invece di utilizzare javax .persistence.SequenceGenerator, utilizzare org.hibernate.annotations, in questo modo:

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

    @ org.hibernate.annotations.GenericGenerator (name = "Question_id_sequence", la strategia = "sequenza", i parametri = {@parameter (name = "sequenza", value = "S_QUESTION")})

Ho provato entrambi i modi, che funziona bene.

2

Uso su PostgreSQL e funziona perfettamente.

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

Creare il nome della sequenza in Oracle, ad esempio contacts_seq. Nella tua classe POJO. Definire la seguente annotazione per la sequenza.

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

allocationSize e incrementBy sono cose completamente diverse.

Hibernate utilizza naturalmente la sequenza creata in DB ma, in base a allocazione, è possibile che si verifichi un gap nel valore generato.

Per esempio- Let assumere valore di sequenza corrente è 5, incremento da 1 a db, e allocationSize predefinito 50.

ora si vuole salvare una collezione di 3 elementi attraverso hibernate, poi Hibernate assegnerà l'ID generato 250, 251, 252

Questo è per scopi di ottimizzazione. Hibernate non deve tornare a db e recuperare il successivo valore incrementato.

Se non si desidera che questa impostazione solo allocationSize = 1 come già risposto farà lo scopo

3

Ho avuto lo stesso problema, mentre l'aggiornamento da 3.5.5 a 5.0.6.Final.

ho risolto dalla mappatura ri-configurazione nel file HBM da:

<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

È necessario impostare increment_size su 1? Non è il valore predefinito? –

Problemi correlati