Problem mt JPA Id-Generators

marky8264

Aktives Mitglied
hallo,

ich habe ein Problem, was ich nicht verstehe. Dabei habe ich eine MySQL-DB, auf welcher ich eine Tabelle habe, bei der der Primärschlüssel automatisch generiert werden soll und zwar wie folgt:
Java:
@Entity
@Table(name="my_entity")
public class MyEntity{
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	@Column(name="r_id")
	private long id;
....
}

allerdings wenn ich nun eine neue Zeile speichern möchte, dann wird brav eine Id generiert, die auch in Ordnung ist, aber wenn nun die Transaktion aus irgendeinen Grund abgebrochen wird, dann geht mir diese Id verloren. Sprich wenn ich momentan "14" habe und es tritt ein Fehler auf, dann ist die nächste "15" und nicht "14" :bahnhof:.

Aber ich brauch leider eine fortlaufende Id, welche keine Lücken haben darf :(

Kann mir jemand bitte weiterhelfen.
mfg
 

hexx

Mitglied
Dafür sind sowohl Auto-Increments als aus Sequences nicht designed. Wenn Du wirklich einen lückenlosen Zähler brauchst, musst du das über striktes Lockíng selber implementieren.

Überleg dir aber vorher genau, ob du den lückenlosen Zähler wirklich brauchst. Mit dem Locking baust du dir einen ziemlichen Flaschenhals in deine Applikation.

Für MySQL & JPA gibt es hier ein Beispiel [1]. Für dich interessant, der naïve native Ansatz und das JPA Beispiel.

[1]http://tedyoung.me/2011/04/14/jpa-counters-and-sequences/
 

marky8264

Aktives Mitglied
erstmals danke für die schnelle Antwort.

Leider brauch ich eine lückenlose, da es sich um eine Rechnungsnr. handelt.

ich habe mir das Beispiel einmal angesehen und dabei ist mir eine Frage gekommmen. Wenn ich das Ganze innerhalb einer Transaktion mache, dann bringt mir ja das Locking eig. nichts, weil die Änderungen für andere erst nach dem Commit sichtbar werden oder?

mfg
 

hexx

Mitglied
...weil die Änderungen für andere erst nach dem Commit sichtbar werden oder?

Und genau deswegen der Read-Lock. Wenn zeitgleich (währen die erste Transaktion noch läuft) eine weitere Rechnung erstellt wird, hätte die sonst die selbe Rechnungsnummer, weil Änderungen eben noch nicht sichtbar sind. Erst der Read-Lock erzwingt die strenge Monotonie, da die zweite Transaktion solange warten muss, bis die erste committed wurde.
 
M

maki

Gast
Rechnungsnummer darf nicht zum Schlüssel in der DB werden, so einfach ist das.
Eine ID hat rein technisch zu sein, ohne jede fachliche Beduetung, dann gibt es in jeder Hinsicht weniger Probleme.
 

hexx

Mitglied
Rechnungsnummer darf nicht zum Schlüssel in der DB werden, so einfach ist das.
Eine ID hat rein technisch zu sein, ohne jede fachliche Beduetung, dann gibt es in jeder Hinsicht weniger Probleme.

Das stimmt. Das Problem, die Rechnungsnummern streng Monoton und ohne Lücken zu erzeugen, bleibt aber das Gleiche.
 

marky8264

Aktives Mitglied
Und genau deswegen der Read-Lock. Wenn zeitgleich (währen die erste Transaktion noch läuft) eine weitere Rechnung erstellt wird, hätte die sonst die selbe Rechnungsnummer, weil Änderungen eben noch nicht sichtbar sind. Erst der Read-Lock erzwingt die strenge Monotonie, da die zweite Transaktion solange warten muss, bis die erste committed wurde.

Asso, jetzt verstehe ich es, danke.
Ich habe es einmal kurz ausgetestet und bin auf eine weiteres Problem gestoßen:

SQL:
UPDATE counter SET value = LAST_INSERT_ID(value + 1);
SELECT LAST_INSERT_ID();
The first statement updates the counter, and stores its updated value in a thread-local database variable called LAST_INSERT_ID. We can retrieve the value safely with a subsequent SELECT statement.

Ich verstehe nun nicht, wie das mit der Variable "LAST_INSERT_ID" funktioniert. Muss ich diese irgendwie anlegen oder definieren vorher? :bahnhof:

Rechnungsnummer darf nicht zum Schlüssel in der DB werden, so einfach ist das.
Eine ID hat rein technisch zu sein, ohne jede fachliche Beduetung, dann gibt es in jeder Hinsicht weniger Probleme.
Also ich verstehe diese Diskussion nicht ganz ???:L, weil ich mir denke, dass es nicht gerade ein gutes Design ist. Wenn ich einen künstlichen Schlüssel erzeugen soll, der wiederum gleich der Rechnungsnr. ist, dann kann ich mir gleich diese Spalte sparen und die Rechnungsnr. verwenden.
mfg
 

Deros

Bekanntes Mitglied
LAST_INSERT_ID

die ID sollte immer ein künstlicher Wert sein, das ist einfach Best-Practise und er ist eben nicht immer genau der Rechnungsnummer das hast du doch jetzt schon festgestellt.
 
M

maki

Gast
Also ich verstehe diese Diskussion nicht ganz ???:L, weil ich mir denke, dass es nicht gerade ein gutes Design ist. Wenn ich einen künstlichen Schlüssel erzeugen soll, der wiederum gleich der Rechnungsnr. ist, dann kann ich mir gleich diese Spalte sparen und die Rechnungsnr. verwenden.
mfg
Hi,

das ist keine "Diskussion", fachliche Schlüssel sind keine Gute Wahl, das ist ein Fakt und gehört zu den Grundlagen von DB Design.

Probleme damit:
Hin und wieder wird es vorkommen, dass du so eine Rechnungsnummer ändern musst, weil die Sachbearbeiter das eben so brauchen.
Mit fachlichen Schlüsseln hast du da sehr viel Aufwand, Datensätze löschen und neu anlegen, denn PKs kann man nicht ändern, natürlich musst du alle Datensätze, welche diese ID Referenzieren auch ändern bzw. löschen und neu anlegen.. wohlgemerkt, wenn die DB oder JPA Ids vergibt, kannst du die zu verwendende Nummer gar nicht vorgeben...

Dass du trotzdem sowas wie einen "Rechnungsnummer Generator" brauchst ist klar, aber den kannst du dir selber schreiben und hast dann auch mehr Einfluss darauf welche Nummern wie vergeben werden.
 

marky8264

Aktives Mitglied
Probleme damit:
Hin und wieder wird es vorkommen, dass du so eine Rechnungsnummer ändern musst, weil die Sachbearbeiter das eben so brauchen.
Mit fachlichen Schlüsseln hast du da sehr viel Aufwand, Datensätze löschen und neu anlegen, denn PKs kann man nicht ändern, natürlich musst du alle Datensätze, welche diese ID Referenzieren auch ändern bzw. löschen und neu anlegen.. wohlgemerkt, wenn die DB oder JPA Ids vergibt, kannst du die zu verwendende Nummer gar nicht vorgeben...

Ok, in einem solchen Fall kann ich es verstehen, aber in meinen Fall wird es so etwas nicht geben, da die Rechnungen nicht änderbar sein sollen. Somit entspricht der Künstliche dem Natürlichen (Rechnungsnr.) und sollte es mal zu einer Lücke des Künstlichen kommen, dann muss ich ja auch diese irgendwie Begründen. Deswegen finde ich, dass es in meinen Fall keine Rolle spielt. :)

Dass du trotzdem sowas wie einen "Rechnungsnummer Generator" brauchst ist klar, aber den kannst du dir selber schreiben und hast dann auch mehr Einfluss darauf welche Nummern wie vergeben werden.
Dieses Argument verstehe ich nicht ganz jetzt :bahnhof:, ich muss ja sowieso einen Generator schreiben und ob ich dann den für den PK nehme oder noch einen zusätzlichen Generator dafür einstelle, macht doch keinen Unterschied mehr.
 
M

maki

Gast
Ok, in einem solchen Fall kann ich es verstehen, aber in meinen Fall wird es so etwas nicht geben, da die Rechnungen nicht änderbar sein sollen.
Das ist die Theorie, die Realität ist etwas anders.
Mal so gefragt:
wer kann dir garantieren dass niemals eine Rechnugsnummer geändert werden soll?
Selbst wenn nur eine Rechung gelöscht wird, hast du keine zusammenhängenden Ids mehr, du kannst da die Ids Generatoren in der DB nicht nach belieben steuern.

Wie gesagt, gehört alles zu den Grundlagen von DB Design, nix neues...
 

marky8264

Aktives Mitglied
Das ist die Theorie, die Realität ist etwas anders.
Mal so gefragt:
wer kann dir garantieren dass niemals eine Rechnugsnummer geändert werden soll?
Selbst wenn nur eine Rechung gelöscht wird, hast du keine zusammenhängenden Ids mehr, du kannst da die Ids Generatoren in der DB nicht nach belieben steuern.

Wie gesagt, gehört alles zu den Grundlagen von DB Design, nix neues...

Allerdings ist das genau der Punkt, eine Rechnung darf nicht gelöscht werden und auch nicht geändert. Ich verstehe auch allgemein nicht, warum sich die Rechnungsnr. ändern soll? ???:L
mfg
 

KSG9|sebastian

Top Contributor
Sei doch nicht so beratungsresistent...

Fachliche Schlüssel sind Müll

Einige Gründe dafür:

- fachliche Werte können sich gerne mal ändern
- fachliche Werte können wegfallen (Beispiel: Kontonummern für Konten werden durch die IBAN ersetzt, was machst du jetzt mit den Kontonummern in der Datenbank, welche auch noch als Schlüssel fungieren=
- fachliche Schlüssel müssen über jede Ebene weitervererbt werden, weil sie nicht eindeutig sind
- Constraints auf fachliche Schlüssel sollen geändert werden..geht aber nicht weil Schlüsselfeld..

Es ist auch nicht relevant was jetzt im Moment möglich sein soll. Sobald das Programm vier Wochen läuft sind die Anforderungen sowieso ganz anders. :)

Beispiel für die tollen fachlichen Schlüssel:

Code:
Tabelle Bank
BLZ

Tabelle Konten
Kontonummer

Das ist schon kaputt, weil die Kontonummer nur in Verbindung mit der BLZ eindeutig ist..also

Code:
Tabelle Konten
BLZ | Kontonummer

// weiter geht's..
Tabelle KontoInhaber
Kontonummer | Name

Ach..verdammt..Kontonummer und Name sind wieder nicht eindeutig..also

Code:
Tabelle Konten
BLZ | Kontonummer

// weiter geht's..
Tabelle KontoInhaber
BLZ | Kontonummer | Name

Oh..ne BLZ beim Kontoinhaber..gut...

Ich hab einmal ein Projekt erlebt in dem das durchgezogen wurde, weil einige Pfeiffen meinten das wäre ja soooo toll...auf unterster Ebene im Model hatten wir dann Tabellen welche zwei, drei eigene Felder hatten und 30 Primärschlüsselfelder, welche aus dem oberen Hierarchien geerbt wurden..geil.

Und irgendwann kam mal einer her und meinte, "das Feld xy Feld weg, macht das mal weg"...ich bin in Lachen ausgebrochen...unmöglich :D

Also - machs gleich richtig und nimm eine technische ID. Und dann kannst du deinen RechnungsnummernGenerator auch losgelöst davon bauen..ist eh schöneres Design.
 

marky8264

Aktives Mitglied
Sei doch nicht so beratungsresistent...
Es tut mir leid, wenn ich diesen Eindruck erwecke, den das ist nicht meine Absicht. :oops:

Ich verstehe ja was ihr meint, technische Schlüssel sind in vielen Fällen besser (wie eben im Bsp mit der Bank). ;)

Nur wenn ich meine Haltung mal mit meinen Beispiel erklären darf:

Es handelt sich um ein kleines Kassenprogramm, bei dem eben für jeden Einkauf ein Kassenbon (oder Rechnung) erstellt wird. Aus gesetzlichen Gründen müssen alle Eingänge aufgezeichnet werden und dürfen nicht mehr manipuliert werden (oder zumindest müsste diese dokumentiert werden).

Deswegen spielen die Argumente "nachträgliche Änderungen an den Dokumenten" oder "Löschen von Dokumenten) keine Rolle, weil das sowieso nicht gehen darf.

Wenn ich nun einen künstlichen Schlüssel dazulege, dann muss dieser ebenfalls fortlaufend sein, damit eine Eindeutigkeit entsteht und kommt es dann zu einer Lücke im technischen Schlüssel, müsste ich diese auch begründen.
Somit müsste ich auch die jeweiligen Logs aufbewahren und dies sehe ich eher als zusätzlichen Overhead. Oder ich setzte den gleichen Mechanismus wie bei der Rechnungsnr-Generierung ein, allerdings würde ich dann wieder an der selben Stelle sein.

Ich bin zwar kein Jurist, aber ich schätze, dass es in der nächsten Jahren sicher nicht dazu kommen wird, dass keine Kassebon-Ids oder Rechnungsnr. mehr benötigt werden. ;)

Wie gesagt, ich bin dankbar für jede Hilfe die bekomme ;):applaus:.
mfg
 
M

maki

Gast
Es handelt sich um ein kleines Kassenprogramm, bei dem eben für jeden Einkauf ein Kassenbon (oder Rechnung) erstellt wird. Aus gesetzlichen Gründen müssen alle Eingänge aufgezeichnet werden und dürfen nicht mehr manipuliert werden (oder zumindest müsste diese dokumentiert werden).
Ich kann dir nur aus persönlicher Erfahrung sagen:
Du täuscht dich da.

Wenn ich nun einen künstlichen Schlüssel dazulege, dann muss dieser ebenfalls fortlaufend sein, damit eine Eindeutigkeit entsteht und kommt es dann zu einer Lücke im technischen Schlüssel, müsste ich diese auch begründen.
Der technische Schlüssel kann Lücken enthalten, etc. pp., den technischen Schlüssel generiert die DB, User sehen davon rein gar nix.
Also zieht dein Argument bez. Logs aufbewahren nicht.

Aber wie dem auch sei, man muss sich eben erst selber die Finger verbrennen bevor man glaubt dass eine Herdplatte heiss ist.

Ich könnte jetzt zum 3. mal wiederholen dass es zu den Grundlagen gehört keine fachlichen Schlüssel zu verwenden, aber 2-mal müssen reichen ;)
 

marky8264

Aktives Mitglied
Das bezweifle ich :noe:, den wie gesagt wird sich im Bereich Aufzeichnung nicht soviel ändern in der nächsten Zeit. :)

Der technische Schlüssel darf keine Lücken enthalten, den sonst muss ich doch bei einer Finanzprüfung womöglich erklären warum es eine Lücke gibt. Genau deswegen bräuchte ich ja wieder die Logs, somit zieht das Argument sehr wohl ;).
Der Benutzer sieht den technischen Schlüssel nicht, da hast du recht, aber ein Prüfer braucht sich nur die Datenbank ansehen (was bei MySQL nicht schwer ist) und wen der Zufall will, wird er eine Lücke sehen :(.

Mir geht es nicht um die Theorie, den es ist oft, das die Praxis anders aussieht wie z.B. bei der Normalisierung.

Somit bleibe ich bei meinen Entwurf mit dem fachlichen Schlüssel, weil es meiner Meinung nach in DIESER Situation die performante Lösung ist ;), aber danke für die hilfreichen Tips.

mfg
 

KSG9|sebastian

Top Contributor
Also ich weiß nicht genau woher deine Finanzprüfer kommen..aber wird hatten schon Besuch unter anderem von der BaFin und ähnlichen Organisationen...und die interessieren sich nicht für technische Schlüssel..und die stören sich auch nicht an einer Lücke in einem technischen Schlüssel. Die interessieren sich lediglich für die fachlichen Daten...
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
J PC-Start Problem JDBC Connection Datenbankprogrammierung 10
C Problem mit Apache Poi Datenbankprogrammierung 6
N HSQLDB Problem mit Eclipselink in runnable Jar Datenbankprogrammierung 10
P GroupLayout-Problem Datenbankprogrammierung 12
F XAMPP max connections problem Datenbankprogrammierung 6
C MySQL Problem in phpMyAdmin Oberfläche Datenbankprogrammierung 5
C Problem with INSERT.............ON DUPLICATE KEY Datenbankprogrammierung 3
C Problem with insertion in database. Datenbankprogrammierung 7
F Problem mit Hibernate c3p0 Datenbankprogrammierung 2
W Problem mit Insert in zwei Tabellen Datenbankprogrammierung 8
G MySQL Problem mit MySQL verbindung Datenbankprogrammierung 8
A kleines Problem Datenbankprogrammierung 6
T Problem mit Datenbankverbindung Datenbankprogrammierung 22
V Derby/JavaDB updateRow Problem Datenbankprogrammierung 0
G MySQL Java Problem: Nullpointer Exception obwohl Daten vorhanden sind? Datenbankprogrammierung 2
Nuiton EmbeddedDriver Problem Datenbankprogrammierung 6
A MongoDB Passwort Problem Datenbankprogrammierung 0
O HSQLDB Hibernate Criteria Problem Datenbankprogrammierung 3
F MySQL JDBC Problem Datenbankprogrammierung 5
Anfänger2011 Datenbankstruktur/aufbau (theoretisches Problem) Datenbankprogrammierung 5
M Derby/JavaDB Drop Database problem Datenbankprogrammierung 3
M Derby/JavaDB NOT LIKE problem Datenbankprogrammierung 19
N HSQLDB Problem mit EntityManager Datenbankprogrammierung 7
B MySQL JPAContainer Problem Datenbankprogrammierung 4
K Eclipse Apache Derby Treiber Problem Datenbankprogrammierung 4
C Problem oder Denkfehler mit H2-Database Datenbankprogrammierung 3
E Wie kann man das Problem mit der BLOB-Spalte lösen? Datenbankprogrammierung 1
M Problem mit jcouchdb und CouchDB - UTF8 kein gültiger Zeichentyp Datenbankprogrammierung 4
T MySQL Problem mit Datenbankanbindung Datenbankprogrammierung 4
M INSERT-Problem = integrity constraint violation: foreign key no parent Datenbankprogrammierung 5
P SQL Query Problem Datenbankprogrammierung 14
A MySQL Problem bei Tabelle ausgeben Datenbankprogrammierung 3
Q MySQL JDBC-Treiber Problem Datenbankprogrammierung 2
B SQLite Problem bei Planung der Datenbank [Jeopardy] Datenbankprogrammierung 3
A Problem mit dem Import und Export von Bildern Datenbankprogrammierung 4
P Oracle Problem mit Umlauten Datenbankprogrammierung 9
A Problem mit Create-Statement Datenbankprogrammierung 9
D Problem mit COLUMN_IDENTIFIERS Datenbankprogrammierung 8
Bluedaishi MySQL Abfrage Problem :-) Datenbankprogrammierung 21
M Problem mit mehreren Datasourcen Datenbankprogrammierung 3
R Resultset.last() Problem Datenbankprogrammierung 12
M Problem GroupBy Datenbankprogrammierung 3
S CURRENT_DATE problem Datenbankprogrammierung 2
Gossi Oracle Problem mit group by... Datenbankprogrammierung 22
M MySQL SQL Abfrage Problem Datenbankprogrammierung 6
R MS-SQL Express Login-Problem Datenbankprogrammierung 8
P Lazy-Fetchig und Session-Problem mit Hibernate Datenbankprogrammierung 4
N HSQLDB Problem beim Treiberladen im Jar Datenbankprogrammierung 6
M Problem beim Erstellen einer Query Datenbankprogrammierung 7
C Hibernate ManyToMany zusammengesetzter Primärschlüssel, problem. Datenbankprogrammierung 3
M Problem mit HQL Syntax Datenbankprogrammierung 5
K Db4o Delete Problem Datenbankprogrammierung 11
Mike90 Deadlock/Lock Problem Datenbankprogrammierung 4
T Access 32bit on Win7 64Bit ODBC Problem Datenbankprogrammierung 1
C unverständliches DB Problem (Es ist kein temporärer Systemtabellenbereich mit einer ausreichenden..) Datenbankprogrammierung 5
S ODBC Treiber Problem/oder unvermögen Datenbankprogrammierung 18
J Problem bei Boolean in PreparedStatement Datenbankprogrammierung 5
C MySQL Problem mit UPDATE Abfrage Datenbankprogrammierung 13
C Problem mit SQL-Abfrage Datenbankprogrammierung 5
K Problem mit Datenbankverbindung via Eclipse Datenbankprogrammierung 2
A Problem mit Eintragen von Daten in eine Datenbank mittels DAO Datenbankprogrammierung 4
S Oracle Problem mit PreparedStatement.setString(1,"str") Datenbankprogrammierung 10
B MySQL Problem mit Datenbankanbindung an MySQL Datenbankprogrammierung 2
N Problem bei Erstellung eines Index Datenbankprogrammierung 12
C Hibernate Property-Problem Datenbankprogrammierung 5
J MyBatis - Update Problem Datenbankprogrammierung 4
S JPA: Problem mit Update von Daten Datenbankprogrammierung 7
c_sidi90 Hibernate Problem Table doesnt excist Datenbankprogrammierung 8
M Problem mit JPA - OneToMany-Relation Datenbankprogrammierung 3
I Hibernate: Composite Foreign Key Problem Datenbankprogrammierung 14
S JPA OptimisticLocking Problem Datenbankprogrammierung 11
I Derby/JavaDB Problem mit Befüllung von Tabelle Datenbankprogrammierung 7
JavaKaffee Derby/JavaDB Quartz-WebAnwendung - Connection/Treiber Problem Datenbankprogrammierung 47
I Problem mit ResultSet Datenbankprogrammierung 2
L Excel in MySQL importieren Problem Datenbankprogrammierung 5
S Problem beim Anlegen einer Tabelle Datenbankprogrammierung 5
R MS Access mit Java Problem mit Update Statment Datenbankprogrammierung 13
S MySQL Problem mit SELECT bzw encoding Datenbankprogrammierung 4
T Problem beim schreiben von daten Datenbankprogrammierung 4
M MySQL getConnection - Verbindung Problem Datenbankprogrammierung 2
K Hibernate + MySQL Problem... Datenbankprogrammierung 2
I MySQL MySQL – Proxy Problem Datenbankprogrammierung 4
M Problem mit Hibernate und Named Query Datenbankprogrammierung 1
M Problem mit Hibernate und Access Datenbankprogrammierung 9
C firebird problem Datenbankprogrammierung 5
F Problem mit Datenbankabfrage Datenbankprogrammierung 7
K SQL Problem mit Date Datenbankprogrammierung 3
jeppi MySQL Design-Problem: DB-Verbindung herstellen und halten - JdbcRowSet / Idle-Timeout? Datenbankprogrammierung 9
J sql abfrage ... Problem mit Datumswert Datenbankprogrammierung 3
G MySQL Connection Problem Datenbankprogrammierung 3
O MySQL Problem mit Umlauten?! Datenbankprogrammierung 2
E Hibernate Problem bei bidirektionaler 1:n Verbindung Datenbankprogrammierung 2
D MySQL Problem beim einfügen von Double-Zahlen Datenbankprogrammierung 4
M Oracle Problem mit Resultset Datenbankprogrammierung 11
T Problem bei Zugriff auf Access Datenbank Datenbankprogrammierung 7
W jpmdbc Problem -Beispiel funktioniert nicht Datenbankprogrammierung 9
W Verständnis-Problem JPA Grundlagen Datenbankprogrammierung 5
M Problem Array in BLOB-Feld in DerbyDB zu speichern Datenbankprogrammierung 5
M JPA-Persist Problem Datenbankprogrammierung 2
7 Problem mit Hibernatekonfiguration Datenbankprogrammierung 13

Ähnliche Java Themen

Neue Themen


Oben