JPA atomare Abfrage / Speichern für Multithread-App

8

Ich bin dabei, meinen JPA-Code zu ändern, um Threads zu verwenden. Ich habe einen separaten Entity Manager und eine Transaktion für jeden Thread.

Was ich früher (für die Single-Thread-Umgebung) hatte, war Code wie:

%Vor%

Mit diesem Code in der Multithread-Umgebung bekomme ich doppelte Schlüssel, da, wie ich annehme, getObjectX null für einen Thread zurückgibt, dann wird dieser Thread ausgelagert, der nächste Thread ruft getObjextX auf, ebenfalls null, und dann werden beide Threads Erstelle und behalte ein neues X ().

Kurz vor der Synchronisation, gibt es einen atomaren Weg, um einen Wert mit JPA zu erhalten / zu speichern - wenn-existiert-nicht oder sollte ich meinen Ansatz überdenken

BEARBEITEN:

Ich benutze das neueste Eclipselink und MySql 5.1

EDIT 2:

Ich habe Synchronisation hinzugefügt ... MASSIVE Performance-Treffer (bis zu dem Punkt, dass es nicht verwendet werden kann). Sammeln Sie alle Daten im Hauptthread und führen Sie dann die Kreationen für diesen Thread aus.

    
TofuBeer 07.06.2010, 19:27
quelle

4 Antworten

4

Kurze, traurige Antwort ist, dass die JPA-API das nicht für Sie tun kann. Die gesamte API basiert mehr oder weniger auf dem optimistischen Prinzip der Annahme, dass Dinge funktionieren, und im Falle gleichzeitiger Änderungen auf Ausnahmen.

Wenn dies häufig passiert, gibt es wahrscheinlich eine andere Komponente (was auch immer foo erzeugt?), die davon profitieren könnte, threadsicher gemacht zu werden, als eine Alternative zur Synchronisierung um die Abfrage + create.

    
Affe 07.06.2010, 20:17
quelle
3

Einige "hack" zu beachten:

  • implementieren hashCode() und equals() basierend auf dem Geschäftsschlüssel der Objekte (nicht der generierten ID)
  • synchronisieren auf:

    %Vor%

Sie erhalten also nur in den relevanten Fällen Sperren.

    
Bozho 07.06.2010 20:36
quelle
2

Ich denke, Sie müssen den Feldern, die in "jpaQuery" verwendet werden, eine eindeutige Einschränkung hinzufügen, damit die Datenbank keine doppelten Zeilen mit denselben Kriterien erstellen kann, die in den Einschränkungen für diese Abfrage verwendet werden. Der aufrufende Code muss die resultierende Ausnahme, die als Ergebnis der Einschränkungsverletzung auftritt, abfangen (idealerweise wird es eine EntityExistsException sein, aber die Spezifikation ist in diesem Fall nicht klar).

    
Michael Barker 07.06.2010 19:51
quelle
0

Sind Sie sicher, dass Sie mehrere Entity Manager benötigen? In einer ähnlichen Situation verwende ich nur einen Entitymanager und einfache Lock-Objekte pro Methode:

%Vor%

Bearbeiten: OK, ich kann nicht viel über die Leistung hinaus tun, außer zu sagen, dass es in meinen Apps gut funktioniert, aber für die Eindeutigkeit verwende ich etwas wie dieses:

%Vor%     
Sean Patrick Floyd 07.06.2010 20:17
quelle

Tags und Links