Wie man @lock
timeout für die Abfrage spezifiziert.
Ich benutze Orakel 11g, ich hoffe, ich kann etwas wie 'select id from table where id = ?1 for update wait 5'
verwenden.
Ich habe eine Methode wie diese definiert,
%Vor% es scheint für immer gesperrt zu sein.
Ich setze javax.persistence.lock.timeout=0
in LocalContainerEntityManagerFactoryBean.jpaProperties
, aber nicht beeinflusst.
Um Objekte pessimistisch zu sperren, setzen Sie den Sperrmodus auf
PESSIMISTIC_READ
,PESSIMISTIC_WRITE
, oderPESSIMISTIC_FORCE_INCREMENT
.Wenn eine pessimistische Sperre nicht erhalten werden kann, aber der Sperrfehler führt nicht zu einem Transaktions-Rollback, ein
LockTimeoutException
ist geworfen.Pessimistische Sperrzeitüberschreitungen
Die Dauer in Millisekunden, die der Persistenzanbieter haben sollte Warten auf eine Sperre für die Datenbanktabellen kann mit angegeben werden die Eigenschaft javax.persistence.lock.timeout. Wenn die Zeit es braucht eine Sperre erhalten, übersteigt den Wert dieser Eigenschaft, a
LockTimeoutException
wird geworfen, aber die aktuelle Transaktion wird nicht für Rollback markiert. Wenn diese Eigenschaft auf 0 festgelegt ist, wird Persistenzanbieter sollte einLockTimeoutException
werfen, wenn es kann nicht sofort eine Sperre erhalten.Wenn
javax.persistence.lock.timeout
an mehreren Stellen gesetzt ist, wird die Der Wert wird in der folgenden Reihenfolge ermittelt:
- Das Argument für eines der
EntityManager
oderQuery methods
.- Die Einstellung in der
@NamedQuery
Annotation.- Das Argument für die Methode
Persistence.createEntityManagerFactory
.- Der Wert im Deployment-Deskriptor
persistence.xml
.
@Lock
wird auf CRUD-Methoden ab Version 1.6 von Spring Data JPA unterstützt (tatsächlich gibt es bereits ein milestone verfügbar). Weitere Informationen finden Sie in diesem Ticket .
Mit dieser Version deklarieren Sie einfach Folgendes:
%Vor% Dies führt dazu, dass der CRUD-Implementierungsteil des Backing-Repository-Proxy den konfigurierten LockModeType auf den find(…)
-Aufruf in EntityManager
anwendet.
Die Spring Data pessimistischen @Lock
-Anmerkungen treffen nur auf Abfragen zu (wie Sie darauf hingewiesen haben). Es gibt keine Anmerkungen, von denen ich weiß, dass sie sich auf eine gesamte Transaktion auswirken können. Sie können entweder eine findByOnePessimistic
-Methode erstellen, die findByOne
mit einer pessimistischen Sperre aufruft, oder Sie können findByOne
ändern, um immer eine pessimistische Sperre zu erhalten.
Wenn Sie Ihre eigene Lösung implementieren wollten, könnten Sie das wahrscheinlich tun. Unter der Haube wird die @Lock
Annotation von LockModePopulatingMethodIntercceptor
verarbeitet, was folgendes bewirkt:
Sie könnten einen statischen Lock-Manager erstellen, der eine ThreadLocal<LockMode>
-Elementvariable hat und dann einen Aspekt um jede Methode in jedem Repository legt, die bindResource mit dem in ThreadLocal festgelegten Sperrmodus aufgerufen hat. Auf diese Weise können Sie den Sperrmodus für einzelne Threads festlegen. Sie könnten dann Ihre eigene @MethodLockMode
Annotation erstellen, die die Methode in einen Aspekt umschließt, der den threadspezifischen Sperrmodus vor dem Ausführen der Methode festlegt und ihn nach dem Ausführen der Methode löscht.
Ein Entitätsobjekt kann explizit durch die Sperrmethode gesperrt werden:
%Vor%Das erste Argument ist ein Entitätsobjekt. Das zweite Argument ist der angeforderte Sperrmodus.
Ein TransactionRequiredException
wird ausgelöst, wenn beim Aufruf der Sperre keine aktive Transaktion vorhanden ist, weil explizites Sperren eine aktive Transaktion erfordert.
Ein LockTimeoutException
wird ausgelöst, wenn die angeforderte pessimistische Sperre nicht erteilt werden kann:
PESSIMISTIC_READ
-Sperranforderung schlägt fehl, wenn ein anderer Benutzer (der
repräsentiert durch eine andere EntityManager-Instanz) hält derzeit a
PESSIMISTIC_WRITE
Sperre für dieses Datenbankobjekt. PESSIMISTIC_WRITE
Sperranforderung schlägt fehl, wenn derzeit ein anderer Benutzer vorhanden ist
hält entweder eine PESSIMISTIC_WRITE
lock oder eine PESSIMISTIC_READ
lock an
dieses Datenbankobjekt.Abfragenhinweise können in den folgenden Bereichen (von global bis lokal) festgelegt werden:
Für die gesamte Persistenzeinheit - mit persistence.xml
Eigenschaft:
Für eine EntityManagerFactory - mit der Methode createEntityManagerFacotory
:
Für einen EntityManager - mit der Methode createEntityManager
:
oder mit der setProperty-Methode:
%Vor% Für eine named query
-Definition - mit dem Element hints
:
Für eine bestimmte Abfrageausführung - mit der Methode setHint
(vor der Ausführung der Abfrage):
Für Spring Data 1.6 oder höher können wir die von Spring Data jpa bereitgestellte @Lock-Annotation verwenden.
Auch das Zeitlimit für die Sperrung kann mit @QueryHints eingestellt werden. Anfänglich gab es keine Unterstützung für Abfragehinweis-Annotationen in Standard-CRUD-Methoden, aber sie war nach Fix 1.6M1 verfügbar. Ссылка
Im Folgenden finden Sie ein Beispiel für eine Pessimistische Sperre mit PESSIMISTIC_WRITE-Modus, bei der es sich um eine exklusive Sperre handelt.
%Vor%