Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Wie kann ich das @lock-Timeout in der Spring Data JPA-Abfrage angeben?

Für Spring Data 1.6 oder höher

@Lock wird auf CRUD-Methoden ab Version 1.6 von Spring Data JPA unterstützt (tatsächlich gibt es bereits einen Meilenstein verfügbar). Siehe dieses Ticket für weitere Details.

Mit dieser Version deklarieren Sie einfach Folgendes:

interface WidgetRepository extends Repository<Widget, Long> {

  @Lock(LockModeType.PESSIMISTIC_WRITE)
  Widget findOne(Long id);
}

Dadurch wendet der CRUD-Implementierungsteil des unterstützenden Repository-Proxys den konfigurierten LockModeType auf find(…) an Rufen Sie den EntityManager auf .

Andererseits

Für frühere Version von Spring Data 1.6

Das pessimistische @Lock von Spring Data Anmerkungen gelten nur (wie Sie darauf hingewiesen haben) für Abfragen. Mir sind keine Anmerkungen bekannt, die sich auf eine gesamte Transaktion auswirken können. Sie können entweder ein findByOnePessimistic erstellen Methode, die findByOne aufruft mit einem pessimistischen Schloss oder Sie können findByOne ändern um immer eine pessimistische Sperre zu erhalten.

Wenn Sie Ihre eigene Lösung implementieren möchten, könnten Sie dies wahrscheinlich tun. Unter der Haube das @Lock Anmerkung wird von LockModePopulatingMethodIntercceptor verarbeitet was folgendes bewirkt:

TransactionSynchronizationManager.bindResource(method, lockMode == null ? NULL : lockMode);

Sie könnten einen statischen Sperrmanager erstellen, der einen ThreadLocal<LockMode> hatte Member-Variable und haben dann einen Aspekt, der um jede Methode in jedem Repository gewickelt ist, 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 Ihren eigenen @MethodLockMode erstellen Anmerkung, die die Methode in einen Aspekt einschließen würde, der den Thread-spezifischen Sperrmodus vor dem Ausführen der Methode setzt und ihn nach dem Ausführen der Methode löscht.

Ressourcenlink:

  1. Wie aktiviere ich LockModeType.PESSIMISTIC_WRITE beim Suchen von Entitäten mit Spring Data JPA?
  2. So fügen Sie benutzerdefinierte hinzu Methode zu Spring Data JPA
  3. Spring Data Pessimistic Lock Timeout with Postgres
  4. JPA-Abfrage-API

Verschiedene Beispiele für pessimistische Sperrzeitüberschreitung

Setzen einer pessimistischen Sperre

Ein Entity-Objekt kann explizit durch die Lock-Methode gesperrt werden:

em.lock(employee, LockModeType.PESSIMISTIC_WRITE);

Das erste Argument ist ein Entitätsobjekt. Das zweite Argument ist der angeforderte Sperrmodus.

Eine TransactionRequiredException wird ausgelöst, wenn beim Aufrufen von lock keine aktive Transaktion vorhanden ist, da explizites Sperren eine aktive Transaktion erfordert.

Eine LockTimeoutException wird ausgelöst, wenn die angeforderte pessimistische Sperre nicht gewährt werden kann:

  • Ein PESSIMISTIC_READ Die Sperranforderung schlägt fehl, wenn ein anderer Benutzer (der durch eine andere EntityManager-Instanz repräsentiert wird) derzeit einen PESSIMISTIC_WRITE besitzt dieses Datenbankobjekt sperren.
  • Ein PESSIMISTIC_WRITE Die Sperranforderung schlägt fehl, wenn ein anderer Benutzer derzeit entweder einen PESSIMISTIC_WRITE besitzt lock oder ein PESSIMISTIC_READ dieses Datenbankobjekt sperren.

Festlegen des Abfragehinweises (Bereiche)

Abfragehinweise können in den folgenden Bereichen festgelegt werden (von global bis lokal):

Für die gesamte Persistenzeinheit - unter Verwendung einer persistence.xml Eigenschaft:

<properties>
   <property name="javax.persistence.query.timeout" value="3000"/>
</properties>

Für eine EntityManagerFactory – mit createEntityManagerFacotory Methode:

Map<String,Object> properties = new HashMap();
properties.put("javax.persistence.query.timeout", 4000);
EntityManagerFactory emf =
  Persistence.createEntityManagerFactory("pu", properties);

Für einen EntityManager - mit dem createEntityManager Methode:

Map<String,Object> properties = new HashMap();
properties.put("javax.persistence.query.timeout", 5000);
EntityManager em = emf.createEntityManager(properties);

oder mit der setProperty-Methode:

em.setProperty("javax.persistence.query.timeout", 6000);

Für eine named query Definition - mit den hints Element:

@NamedQuery(name="Country.findAll", query="SELECT c FROM Country c",
    hints={@QueryHint(name="javax.persistence.query.timeout", value="7000")})

Für eine bestimmte Abfrageausführung - mit setHint Methode (vor der Abfrageausführung):

query.setHint("javax.persistence.query.timeout", 8000);

Ressourcenlink:

  1. Sperre in JPA
  2. Pessimistische Sperrzeitüberschreitung