2013-07-24 8 views
6

Ich habe eine Anzahl von Hibernate-Entities mit reinen JPA-Annotationen definiert. Diese verwenden eine vordefinierte Oracle-Sequenz in meiner Datenbank, um Primärschlüsselwerte automatisch zu generieren.JBoss EAP 6.x mit Hibernate-Oracle-Sequenz Doppelter Wert auf Primärschlüssel

@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; 

Wenn dies auf JBoss EAP eingesetzt wird 6.1 alle gut funktioniert zunächst aber nach kurzer Zeit beginnt Hibernate Erzeugen Nachschlüssel auf Einsätze (ORA-00001-Fehler).

Es ist mir egal, ID Bestellung oder Lücken, aber nicht tolerieren doppelte Schlüssel ... Was ist hier los?

Antwort

13

Dies ist nicht gut dokumentiert, viele der Lösungen auf hier und anderen Websites beziehen sich auf ältere Versionen von Hibernate, wo der HiLo sequenceGenerator der Standard war. Aber nach der Untersuchung fand ich die zugrunde liegende Ursache ist, dass JBoss EAP 6

hibernate.id.new_generator_mappings=true 

standardmäßig setzt, die anstelle der älteren Version eine org.org.hibernate.id.enhanced.SequenceStyleGenerator verwendet.

Das Standard-Inkrement des Hibernate SequenceStyleGenerators ist 1 (überprüfen Sie den Code!), JPA überschreibt jedoch den Inkrementwert in diesem Generator auf 50. Dies bedeutet, dass der Generator die Sequenz nextval betrachtet und einen Cache mit 50 IDs verwendet. beginnend mit nextval - 49. Wenn diese erschöpft sind, liest der Generator die nächste Sequenz von Orakel und wiederholt den Vorgang. Sobald die erste Reihe von IDs erschöpft ist, sehen wir doppelte Schlüssel.

So ist die Auflösung:

1) Entweder definieren Sie Ihre Oracle-Sequenz (en) mit einem Zuwachs von 50 der PPV Standard übereinstimmen

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

oder

2) In allocationSize = 1 für die Annotation @SequenceGenerator - dies zwingt den SequenceGenerator zum Zurückgehen, um den nächsten Wert aus der Oracle-Sequenz für jede benötigte ID zu lesen (mit einer möglichen Auswirkung auf die Leistung)

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

oder

3) definieren die Oracle-Sequenz INCREMENT durch einen anderen Wert, und sicherzustellen, dass die allocationSize einstimmt.

Beantwortete meine eigene Frage in der Hoffnung, anderen zu helfen, die dieses Problem ansprechen.

+0

Obwohl ich nach anderen Informationen suche, die Art, wie Sie Informationen hinzugefügt haben, um anderen zu helfen, verdienen +1. – kosa

1

Ihre Antworten sind korrekt; nur ein paar mehr Details.

Einige Beiträge schlagen vor, zu deaktivieren hibernate.id.new_generator_mappings = false.

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

Es gibt einen Unterschied zwischen GenerationType.AUTO und GenerationType.SEQUENCE ist

, wenn Sie AUTO wählen, haben Sie die Hibernate nativen wählen. und wenn Sie SEQUENCE wählen, werden Sie den hilo-Algorithmus für die Sequenzzuweisung anpassen, der absolut nicht mit SequenceStyleGenerator identisch ist. Dies ist NICHT kompatibel, wenn Sie hibernate.id.new_generator_mappings = true/false wechseln.

Also die Antwort 1) ist definitiv die richtige/nach den aktuellen Hibernate/Jboss Empfehlungen.

... und die Antwort Einstellung allocationSize = 1 für alle Entitäten ist keine gute Lösung. http://itdevworld.wordpress.com/2009/12/20/hibernate-sequencegenerator-with-allocationsize1-leads-to-huge-contention/

+1

Dank @skay, ich habe eine Klarstellung hinzugefügt, um 2) über die potenziellen Auswirkungen auf die Leistung einzelner Zuweisungen zu beantworten. Dies kann insbesondere in einer RAC-Umgebung auffallen, wenn die Sequenz mit 'Auftrag' eingerichtet ist. –

+0

Hinweis - die JBoss-Dokumente im Link erwähnen, dass dies eine Hibernate 4.x-Einstellung ist. Es wird auch in Hibernate 3 unterstützt. Verwenden Sie es mit 3.6.0.Final in unserer App .. JBoss AS 7 wird mit 4.x daher, wie ihre Dokumentation darauf verweist. –

Verwandte Themen