2012-03-25 3 views
15

Ho una classe con la seguente definizione:Hibernate genera valori ID negativi quando si utilizza una sequenza di

@Id 
@SequenceGenerator(name = "SEQ_ACE_WORKERS_QUEUE_STATS_ID", sequenceName = "SEQ_ACE_WORKERS_QUEUE_STATS_ID", allocationSize = 500) 
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_ACE_WORKERS_QUEUE_STATS_ID") 
@Column(name = "ID") 
private long Id; 

Quando ci siamo imbattuti su Jboss 4.2.3 ha funzionato bene e ha generato l'ID corretto (a partire dal 1000)

Ora passiamo a jboss 7.1.1 e genera ID negativi! (a partire da -498 e salendo)

Qualche idea del motivo per cui ciò potrebbe accadere?

+1

hai controllato la sequenza corrente in Oracle e l'output di ibernazione della traccia, se viene visualizzata la query di selezione della sequenza successiva corretta e se si copia incolla in sqlplus si ottiene il risultato corretto/uguale/previsto? – HRgiger

risposta

24

Mi sono appena imbattuto in questo problema durante la migrazione da JBoss 6.1 a JBoss 7.1.

Secondo il JBoss AS 7.1 documentazione JPA (https://docs.jboss.org/author/display/AS71/JPA+Reference+Guide#JPAReferenceGuide-Persistenceunitproperties),

JBoss 7.1 imposta automaticamente diverse proprietà Hibernate. Una delle proprietà impostate è hibernate.id.new_generator_mappings che attiva i nuovi generatori di ID che utilizzano algoritmi diversi e non sono retrocompatibili. L'impostazione di questa proprietà su false nel file persistence.xml ripristinerà il comportamento del vecchio generatore di ID.

La documentazione di ibernazione 4 contiene anche informazioni sui nuovi generatori di ID: http://docs.jboss.org/hibernate/core/4.0/manual/en-US/html_single/#mapping-declaration-id-generator.

La documentazione di ibernazione indica chiaramente che i nuovi generatori di ID non sono abilitati di default, ma, come notato sopra, JBoss 7.1 li abilita automaticamente.

+0

Grazie per la risposta, sono già riuscito a trovarlo, ho dimenticato di aggiornarlo qui :( – Tomer

+0

A partire da Hibernate versione 5.0, la proprietà 'hibernate.id.new_generator_mappings' è impostata su' true'. Vedere http: //docs.jboss .org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html # identificatori-generatori –

12

Impostazione hibernate.id.new_generator_mappings-false nel mio persistence.xml era solo la prima parte della soluzione al mio problema:

Per risolvere completamente il problema ho aggiunto il allocationSize-1 nel @SequenceGenerator (che mi è stato omettendo).

30

Il nuovo comportamento è i seguenti:

AllocationSize è una gamma di valori di chiave primaria riservati ai Hibernate. E la selezione di seq.nextval da doppio verrà eseguita solo dopo che l'ibernazione ha consumato questo intervallo di chiavi primarie.

Così si deve dichiarare lo stesso valore su entrambi allocationSize (Hibernate) e la sequenza increment by (DB)

Quando è impostato in modo esplicito allocationSize=500, per esempio su Oracle

create sequence SEQ_ACE_WORKERS_QUEUE_STATS_ID 
     MINVALUE 1 
     MAXVALUE 999999999999999999999999999 
     START WITH 1 
     INCREMENT BY 500 
     NOCACHE 
     NOCYCLE; 

In caso contrario, si noteranno valori negativi o errori di vincolo generati dal DB a causa di collisioni di chiavi primarie.

Quando il server dell'app viene riavviato, noterete il "salto" tra l'ultima chiave primaria assegnata e il numero di sequenza "nuovo" selezionato al riavvio.

Commento finale: valore di default è 50. Quindi, se non si specifica allocationSize sul lato Hibernate, è necessario dichiarare increment by 50 sul lato DB.

+0

Risposta molto utile, in quanto questa informazione apparentemente non si trova nei documenti di Hibernate. –

Problemi correlati