2013-07-24 14 views
6

Ho definito un numero di entità di ibernazione utilizzando annotazioni JPA pure. Questi usano una sequenza Oracle predefinita sul mio database per generare automaticamente i valori delle chiavi primarie.JBoss EAP 6.x con Hibernate Oracle Duplicato sequenza sequenziale su chiave primaria

@Id 
@SequenceGenerator(name = "USERS_ID_GENERATOR", sequenceName = "MY_SEQ") 
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USERS_ID_GENERATOR") 
@Column(name = "U_ID", updatable = false, unique = true, nullable = false, precision = 19) 
private Long id; 

Quando questo viene distribuito a JBoss EAP 6.1 tutto funziona bene inizialmente ma dopo un breve periodo di sospensione inizia a generare chiavi duplicate su inserti (ORA-00001 errori).

Non mi interessa l'ID o gli spazi vuoti, ma non posso tollerare le chiavi duplicate ... Cosa sta succedendo qui?

risposta

13

Questo non è ben documentato, molte delle soluzioni qui e altri siti si riferiscono a versioni precedenti di hibernate in cui il sequencerGenerator HiLo era l'impostazione predefinita. Ma dopo indagini ho scoperto la causa di fondo è che JBoss EAP 6 stabilisce

hibernate.id.new_generator_mappings=true 

per impostazione predefinita, che utilizza un org.org.hibernate.id.enhanced.SequenceStyleGenerator invece della versione precedente.

L'incremento predefinito di Hibernate SequenceStyleGenerator è 1 (controllare il codice!), Tuttavia JPA sovrascrive il valore di incremento in questo generatore su 50. Ciò significa che il generatore guarda la sequenza nextval e mantiene una cache di 50 id da utilizzare, a partire da nextval - 49. Quando questi sono esauriti, il generatore legge la sequenza successiva da Oracle e ripete il processo. Quindi una volta esaurita la prima serie di ID, iniziamo a vedere le chiavi duplicate.

Quindi la risoluzione è:

1) o definire la sequenza (s) Oracle con un valore di incremento del 50 per abbinare il default JPA

CREATE SEQUENCE MY_SEQ 
START WITH 50 
MAXVALUE 9999999999999999999 
INCREMENT BY 50 
NOCYCLE; 

o

2) Aggiungere allocationSize = 1 all'annotazione @SequenceGenerator: forza il SequenceGenerator a tornare a leggere il valore successivo dalla sequenza oracle per ciascun ID richiesto (con un potenziale impatto sulle prestazioni)

@SequenceGenerator(name = "USERS_ID_GENERATOR", sequenceName = "MY_SEQ", allocationSize = 1) 

, o

3) definiscono la sequenza INCREMENT Oracle qualche altro valore, e garantire l'allocationSize corrisponde.

Ho risposto alla mia domanda nella speranza di aiutare gli altri a risolvere questo problema.

+0

Anche se sto cercando altre informazioni, il modo in cui hai aggiunto le informazioni come risposta per aiutare gli altri a meritare +1. – kosa

1

Le risposte sono corrette; solo qualche altro dettaglio

Alcuni post propongono di disattivare hibernate.id.new_generator_mappings = false.

ma secondo https://docs.jboss.org/author/display/AS71/JPA+Reference+Guide#JPAReferenceGuide-Persistenceunitproperties

C'è una differenza tra il GenerationType.AUTO e GenerationType.SEQUENCE

se si sceglie AUTO, dovrai selezionare il nativo di ibernazione. e se si seleziona SEQUENZA, si abbinerà all'algoritmo di hilo per l'assegnazione della sequenza che non è assolutamente la stessa di SequenceStyleGenerator. Questo NON sarà compatibile se cambi hibernate.id.new_generator_mappings = vero/falso.

Quindi la risposta 1) è sicuramente quella corretta/seguendo le attuali raccomandazioni di Hibernate/Jboss.

... e l'impostazione di risposta allocationSize = 1 per tutte le entità non è una buona soluzione. Vedere http://itdevworld.wordpress.com/2009/12/20/hibernate-sequencegenerator-with-allocationsize1-leads-to-huge-contention/

+1

Grazie a @skay, ho aggiunto un chiarimento per la risposta 2) sul potenziale impatto delle prestazioni dei singoli allocaionts. Questo può essere particolarmente evidente in un ambiente RAC se la sequenza è impostata con "ordine". –

+0

Nota: i documenti JBoss nel collegamento indicano che si tratta di un'impostazione di Hibernate 4.x. È anche supportato in Hibernate 3. Usandolo con 3.6.0.Final nella nostra app .. JBoss AS 7 viene fornito con 4.x, quindi come la loro documentazione si riferisce ad esso. –

Problemi correlati