2016-05-01 16 views
0

Ich verwende Java Hibernate.Was ist der Ansatz, um eine Zeile der Tabelle abhängig von Daten einer anderen Tabelle zu aktualisieren, wenn 2 Transaktionen gleichzeitig auftreten und sich gegenseitig beeinflussen

Usecase:

Ich habe 2 Tabellen: A und B Nun, wenn B enthält keine Zeile für eine Accid x mit Status wahr ist, dann Status Accid x in Tabelle A muss ACTIVE anderes es geändert werden sollte INAKTIV bleiben.

Aktueller Status der Tabellen A und B: B enthält 2 Zeilen (mit ID = 1, 2), die jeweils accId als X und Status True enthalten. A enthält 1 Zeile mit accId als X und Status INACTIVE.

Jetzt kommen 2 Aufrufe gleichzeitig, für jede der Zeilen (id = 1, 2) versuchen, den Status von accId X für die entsprechenden Zeilen als falsch zu machen.

Immer wenn ein Aufruf den Status accId false ergibt, mache ich in Tabelle B den Status false für die entsprechende Zeilen-ID und überprüfe in Tabelle B selbst, ob eine andere Zeile mit dem Status true für diese Konto-ID vorhanden ist. Wenn keine solche Zeile vorhanden ist, ändere ich den Status von accId in ACTIVE.

Nun, in meinem Fall, wenn 2 Anrufe zur gleichen Zeit kommen, beide prüfen, ob eine Zeile mit dem Status wahr oder nicht vorhanden ist, da die Transaktion nicht so weit festgeschrieben ist und im Speicher bleibt jeder von ihnen dort findet ist eine Zeile mit Status true noch vorhanden. Daher markieren beide ihren Status als falsch in der Tabelle für ihre jeweiligen Zeilen. Der Status von accId ändert sich jedoch nicht zu ACTIVE in Tabelle A.

So beheben Sie dieses Problem.

Antwort

0

Sie haben ein Nebenläufigkeitsproblem: Sie müssen den Zugriff sperren, wenn einer der Anrufe eintrifft (der erste). Wenn der zweite Anruf eintrifft, muss er warten, bis der erste Anruf abgeschlossen ist und das Problem gelöst ist. Ich glaube, Sie können angeben, dass eine ganze Tabelle während der Transaktion gesperrt werden, aber ich habe nie Java Hibernate verwendet.

Von: https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/transactions.html

11,4. Pessimistisches Sperren

Es ist nicht beabsichtigt, dass Benutzer sich viel Zeit mit Sperrstrategien beschäftigen. In der Regel genügt es, eine Isolationsstufe für die JDBC-Verbindungen anzugeben und dann die Datenbank einfach arbeiten zu lassen. Fortgeschrittene Benutzer möchten jedoch möglicherweise zu Beginn einer neuen Transaktion exklusive pessimistische Sperren erhalten oder Sperren erneut abrufen.

Hibernate verwendet immer den Sperrmechanismus der Datenbank; Es sperrt niemals Objekte im Speicher.

Die LockMode-Klasse definiert die verschiedenen Sperrstufen, die von Hibernate erworben werden können. Eine Sperre wird durch folgende Mechanismen erzielt:

LockMode.WRITE is acquired automatically when Hibernate updates or inserts a row. 

LockMode.UPGRADE can be acquired upon explicit user request using SELECT ... FOR UPDATE on databases which support that syntax. 

LockMode.UPGRADE_NOWAIT can be acquired upon explicit user request using a SELECT ... FOR UPDATE NOWAIT under Oracle. 

LockMode.READ is acquired automatically when Hibernate reads data under Repeatable Read or Serializable isolation level. It can be re-acquired by explicit user request. 

LockMode.NONE represents the absence of a lock. All objects switch to this lock mode at the end of a Transaction. Objects associated with the session via a call to update() or saveOrUpdate() also start out in this lock mode. 

Die „explizite Benutzeranforderung“ auf eine der folgenden Weise ausgedrückt wird:

A call to Session.load(), specifying a LockMode. 

A call to Session.lock(). 

A call to Query.setLockMode(). 

Wenn Session.load() mit UPGRADE oder UPGRADE_NOWAIT aufgerufen und das angeforderte Objekt wurde noch nicht von der Sitzung geladen, das Objekt wird mit SELECT ... FOR UPDATE geladen. Wenn load() für ein Objekt aufgerufen wird, das bereits mit einer weniger restriktiven Sperre als die angeforderte geladen ist, ruft Hibernate lock() für dieses Objekt auf.

Session.lock() führt eine Versionsnummerprüfung durch, wenn der angegebene Sperrmodus READ, UPGRADE oder UPGRADE_NOWAIT ist. Im Fall von UPGRADE oder UPGRADE_NOWAIT wird SELECT ... FOR UPDATE verwendet.

Wenn der angeforderte Sperrmodus von der Datenbank nicht unterstützt wird, verwendet Hibernate einen geeigneten Alternativmodus, anstatt eine Ausnahme auszulösen. Dies stellt sicher, dass Anwendungen portabel sind.

+0

danke, ich habe versucht, mit pessimistischen lesen auf der Abfrageebene, aber nicht in der Lage, Wartezeit für die zweite Transaktion, daher LockAcquisitionException. – Talha