2010-09-08 8 views
7

Ich schreibe eine Anwendung, die Entitäten von einer Drittanbieter-Datenquelle in unser eigenes Schema synchronisiert, mit einem Transformations-/Mapping-Schritt dazwischen. Ich verwende Hibernate, um die Entitäten in unserem eigenen Schema darzustellen und zu persistieren. Ein Problem, auf das ich stoße, ist, dass ich einen eindeutigen mehrspaltigen Schlüssel an einem meiner Tische habe. Das Verhalten, das ich gerne sehen möchte, ist analog zu einem Upsert: Wenn Hibernate eine Entität persistiert und eine eindeutige Constraint-Verletzung erkennt, führt sie stattdessen eine Aktualisierung durch. Wir verwenden MySQL, das eine INSERT ... ON DUPLICATE KEY UPDATE-Syntax bietet, aber ich bin mir nicht sicher, wie oder ob Hibernate davon Gebrauch machen kann?Wie kann das Verhalten bei der Verwendung von Hibernate nachgeahmt werden?

Ich denke, ich könnte immer versuchen, die Einfügung, und wenn ich eine Ausnahme abfangen, ein Update, aber das scheint hacky und suboptimal. Irgendwelche Tipps auf eine saubere Art und Weise dies zu tun?

Antwort

4

Wir verwenden MySQL, das eine INSERT ... ON DUPLICATE KEY UPDATE-Syntax bietet, aber ich bin mir nicht sicher, wie oder ob Hibernate davon Gebrauch machen kann?

Es sieht aus wie jemand did it durch Überschreiben der sql-insert Anweisung von Hibernate für diese Entität. Wenn es Ihnen nichts ausmacht, nicht portierbar zu sein (und wahrscheinlich eine gespeicherte Prozedur zu verwenden), sehen Sie sich das an.

Ich vermute, ich könnte immer versuchen, die Einfügung, und wenn ich eine Ausnahme abfangen, ein Update, aber das scheint hacky und suboptimal. Irgendwelche Tipps auf eine saubere Art und Weise dies zu tun?

Eine andere Option wäre:

  1. eine select auf der einzigartigen
  2. Schlüssel durchführen, wenn Sie einen Datensatz finden, aktualisieren Sie es
  3. wenn Sie keinen Datensatz finden, erstellen Sie es

Aber wenn Sie den ganzen Tisch (e) während des Prozesses zu sperren, können Sie einig race-Bedingung in einem Gesicht Multi-Threaded und verteilte Umgebung und Schritt # 3 kann möglicherweise fehlschlagen. Stellen Sie sich zwei gleichzeitige Threads:

Gewinde 1:

  • beginnen trans
  • führen eine Auswahl auf einem Schlüssel
  • keinen Datensatz gefunden
  • erstellen einen Datensatz
  • begehen

Gewinde 2:

  • beginnen trans
  • auf dem gleichen Schlüssel
  • kein Rekord
  • gefunden
  • eine Auswahl führt einen Datensatz
  • commit (FAIL erstellen! weil Faden 1 war schneller und ein Datensatz mit dem gleichen eindeutigen Schlüssel existiert jetzt) ​​

Also würde man sowieso eine Art von Wiederholungsmechanismus implementieren muß (Sperren die gesamte Tabelle (n) ist keine gute Option IMO) .

3

Die Race-Bedingung kann durch „wählen ... for update“

+3

Wenn die Auswahl Matches keine Zeilen zu vermeiden, werden keine Zeilen von „for update“ gesperrt werden. Die Wettlaufbedingung wird nicht vermieden. –