it-swarm.com.de

Ruhezustand mit Oracle-Sequenz verwendet es nicht

Ich habe den Ruhezustand für die Verwendung der Oracle-Sequenz konfiguriert. Die Sequenz wird mit cache = 20, inkrement = 1 erstellt.

Alles funktioniert gut, hibernate persistente Entitäten. Der ID-Wert ist seltsam: 50,51 .... 76,201,202 ... 209,1008,1009,5129,5130 .... 

Wenn ich nach dem Sequenzwert frage (wähle hibernate_sequence.nextval aus dual), bekomme ich einen Wert wie 2,3,4 ...

Wenn ich das SQL-Debugging im Ruhezustand aktiviere, gibt es Zeit für Zeit, "select hibernate_sequence.nextval from dual" aufzurufen.

@Id
@Column(name = "ID", insertable = false, updatable = false)
@SequenceGenerator(name = "SequenceIdGenerator", sequenceName = "HIBERNATE_SEQUENCE")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SequenceIdGenerator")
private Long id;
19
Vlada

Dies liegt daran, dass der SequenceGenerator kein Sequenzgenerator ist. Es ist ein Sequenz-Hi-Lo-Generator. Das heißt, beim ersten Aufruf erhält es den nächsten Wert aus der Sequenz (beispielsweise 6), multipliziert diesen Wert mit 50 und liefert das Ergebnis (300). Beim nächsten Aufruf wird 301 zurückgegeben (ohne zu der Sequenz zu gehen) usw., bis 349 erreicht ist. Dann fragt es die Sequenz nach dem nächsten Wert und erhält 7, die wiederum mit 50 multipliziert wird, um 350 zu erhalten. My Die Beschreibung des Algorithmus könnte um eins abweichen, aber Sie haben die Idee.

Wenn Sie die Anwendung anhalten und starten, weist dies Lücken auf. Es ist jedoch effizienter als ein reiner Sequenzgenerator, da er in 50 Generationen nur einmal einen Datenbankaufruf durchführt.

Siehe http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#mapping-declaration-id-enhanced-optimizers und http: //docs.jboss. org/hibernate/core/3.6/reference/de-de/html_single/# Mapping-Deklaration-ID-Generator für Details.

32
JB Nizet

Ich gehe davon aus, dass Ihre Frage ist, dass die Werte der ID-Spalte in der Datenbank keine natürliche Reihenfolge sind, sondern warum Sie Lücken sehen:

Ein bisschen Hintergrund:

  • Bei jedem Aufruf von select HIBERNATE_SEQUENCE.nextval from DUAL wird der Wert der Sequenz erhöht.
  • Da Ihr Folgename generisch und nicht tabellenspezifisch ist, werden bei Verwendung mehrerer Entitäten, die alle HIBERNATE_SEQUENCE als ID-Generator verwenden, die Werte aus den Folgen in allen Entitäten verwendet.
  • Wenn eine andere Anwendung HIBERNATE_SEQUENCE verwendet, wird der Wert ebenfalls übersprungen.
  • Wenn Sie CACHE = 20 verwenden, greift Oracle Sequenznummern in Blöcken von 20 und verwendet dann einen internen Cache, um die Zahlen zurückzugeben. Dies kann dazu führen, dass Zahlen übersprungen werden, wenn der Cache verloren geht (z. B. wenn die Datenbank heruntergefahren wird).
  • Wenn Zeilen aus Ihrer Datenbank gelöscht werden, ändert sich der Sequenzwert nicht

Stellen Sie sich beispielsweise das folgende Szenario vor:

Sie haben zwei Entitäten Entity1 und Entity2, die HIBERNATE_SEQUENCE als ID-Generator verwenden:

  1. Der aktuelle HIBERNATE_SEQUENCE-Wert ist 100
  2. Eine Entity1 wird eingefügt (verwendet HIBERNATE_SEQUENCE, die 101 zurückgibt)
  3. Eine Entity2 wird eingefügt (verwendet HIBERNATE_SEQUENCE, die 102 zurückgibt)
  4. Eine Entity2 wird eingefügt (verwendet HIBERNATE_SEQUENCE, die 103 zurückgibt)
  5. Die Entity2 mit der ID 103 wird gelöscht
  6. Sie führen select HIBERNATE_SEQUENCE.nextval from DUAL manuell aus (gibt 104 zurück)
  7. Eine Entity1 wird eingefügt (verwendet HIBERNATE_SEQUENCE, die 105 zurückgibt)
  8. Eine Entity2 wird eingefügt (verwendet HIBERNATE_SEQUENCE, die 106 zurückgibt)

Am Ende haben Sie also:

  • Entität1 mit IDs (101, 105)
  • Entity2 mit IDs (102, 106)

was die Lücken erklärt.

BEARBEITEN:

Selbst wenn der @SequenceGenerator so eingerichtet wurde, dass er die SequenceGenerator anstelle der SequenceHiLoGenerator verwendet (wie von JB Nizet darauf hingewiesen wurde, was meiner Meinung nach eine bessere Erklärung für die Lücken darstellt), sind Lücken in IDs, die durch Sequenzen erzeugt werden, ein übliches Vorkommen.

6
beny23
CREATE SEQUENCE SEQ_SEQUENCENAME INCREMENT BY 1 START WITH 1 MINVALUE 1;
grant all on SEQ_SEQUENCENAME to public;

@Id
@Column(name = "ID", unique = true, nullable = false)
@SequenceGenerator(name = "SequenceIdGenerator", sequenceName = "SEQ_SEQUENCENAME")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SequenceIdGenerator")
private int Id;
0
Yogi