it-swarm.com.de

Wie man @lock Timeout im Frühjahr Daten JPA-Abfrage angeben?

Festlegen des Zeitlimits für @lock für die Abfrage. Ich verwende Oracle 11g, ich hoffe, ich kann so etwas wie 'select id from table where id = ?1 for update wait 5' verwenden.

Ich definierte Methode wie folgt,

@Lock(LockModeType.PESSIMISTIC_WRITE)
Stock findById(String id);

es scheint für immer zu sperren. Ich setze javax.persistence.lock.timeout=0 in LocalContainerEntityManagerFactoryBean.jpaProperties, aber nicht betroffen.

13
user2501759

Um Entitäten pessimistisch zu sperren, setzen Sie den Sperrmodus auf PESSIMISTIC_READ, PESSIMISTIC_WRITE oder PESSIMISTIC_FORCE_INCREMENT.

Wenn eine pessimistische Sperre nicht erhalten werden kann, der Sperrfehler Jedoch nicht zu einem Transaktionsrollback führt, wird eine LockTimeoutException Geworfen.

Pessimistische Sperrzeitlimits

Die Zeit in Millisekunden, die der Persistenzanbieter warten soll, um eine Sperre für die Datenbanktabellen zu erhalten, kann mit Der Eigenschaft javax.persistence.lock.timeout angegeben werden. Wenn die Zeit, bis Eine Sperre erlangt, den Wert dieser Eigenschaft übersteigt, wird eine LockTimeoutException ausgelöst, die aktuelle Transaktion Wird jedoch nicht für das Zurücksetzen markiert. Wenn diese Eigenschaft auf 0 gesetzt ist, sollte der Persistenz-Provider Eine LockTimeoutException werfen, wenn Keine sofortige Sperre erhalten kann.

Wenn javax.persistence.lock.timeout an mehreren Stellen festgelegt ist, wird der Wert In der folgenden Reihenfolge bestimmt:

  1. Das Argument für eine der Variablen EntityManager oder Query methods.
  2. Die Einstellung in der Annotation @NamedQuery.
  3. Das Argument für die Persistence.createEntityManagerFactory-Methode.
  4. Der Wert im persistence.xml-Implementierungsdeskriptor.

Für Spring Data 1.6 oder höher

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

Mit dieser Version erklären Sie einfach Folgendes:

interface WidgetRepository extends Repository<Widget, Long> {

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

Dies bewirkt, dass der CRUD-Implementierungsteil des Backing-Repository-Proxy den konfigurierten LockModeType auf den Aufruf find(…) der Variable EntityManager anwendet.

Auf der anderen Seite,

Für frühere Version von Spring Data 1.6

Die pessimistischen @Lock-Annotationen von Spring Data gelten (wie Sie darauf hingewiesen haben) nur für Abfragen. Es gibt keine Anmerkungen, von denen ich weiß, dass sie die gesamte Transaktion beeinflussen 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 eine eigene Lösung implementieren wollten, könnten Sie dies wahrscheinlich tun. Unter der Haube wird die @Lock-Annotation von LockModePopulatingMethodIntercceptor verarbeitet, was Folgendes bewirkt:

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

Sie könnten einen statischen Sperrenmanager erstellen, der über eine Membervariable ThreadLocal<LockMode> verfügt, und dann einen Aspekt um jede Methode in jedem Repository legen, der bindResource mit dem in der ThreadLocal festgelegten Sperrmodus aufgerufen hat. Auf diese Weise können Sie den Sperrmodus pro Thread festlegen. Sie könnten dann eine eigene @MethodLockMode-Annotation erstellen, die die Methode in einen Aspekt umschließt, der den Thread-spezifischen Sperrmodus vor der Ausführung der Methode festlegt und nach dem Ausführen der Methode löscht.

Ressourcenlink:

  1. Wie kann ich LockModeType.PESSIMISTIC_WRITE aktivieren, wenn Entitäten mit Spring Data JPA nachgeschlagen werden?
  2. Hinzufügen einer benutzerdefinierten Methode zu Spring Data JPA
  3. Spring Data Pessimistic Lock Timeout mit Postgres
  4. JPA-Abfrage-API

Verschiedene Beispiele für pessimistisches Sperrzeitlimit

Pessimistische Sperre einstellen

Ein Entitätsobjekt kann durch die Sperrmethode explizit 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 der Sperre keine aktive Transaktion vorhanden ist, da das explizite Sperren eine aktive Transaktion erfordert.

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

  • Eine PESSIMISTIC_READ-Sperranforderung schlägt fehl, wenn ein anderer Benutzer (der durch eine andere EntityManager-Instanz Repräsentiert wird) derzeit eine PESSIMISTIC_WRITE-Sperre für dieses Datenbankobjekt besitzt.
  • Eine PESSIMISTIC_WRITE-Sperranforderung schlägt fehl, wenn ein anderer Benutzer derzeit Entweder eine PESSIMISTIC_WRITE-Sperre oder eine PESSIMISTIC_READ-Sperre für Dieses Datenbankobjekts besitzt.

Abfragehinweis festlegen (Bereiche)

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

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 der 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 der 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 dem 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 der setHint-Methode (vor der Abfrageausführung):

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

Ressourcenlink:

  1. Sperren in JPA
  2. Pessimistisches Sperrzeitlimit
15
SkyWalker

Sie können @QueryHints in Spring Data verwenden:

@Lock(LockModeType.PESSIMISTIC_WRITE)
@QueryHints({@QueryHint(name = "javax.persistence.lock.timeout", value ="5000")})
Stock findById(String id)
8

Für Spring Data 1.6 oder höher können wir die @Lock-Annotation verwenden, die von Spring Data jpa bereitgestellt wird.

Die Sperrzeit kann auch mit @QueryHints festgelegt werden. Ursprünglich gab es keine Unterstützung für Abfragehinweise in Standard-CRUD-Methoden, diese waren jedoch nach Fix 1.6M1 verfügbar. https://jira.spring.io/browse/DATAJPA-173

Im Folgenden finden Sie ein Beispiel für eine Pessimistische Sperre mit dem Modustyp PESSIMISTIC_WRITE, bei der es sich um eine exklusive Sperre handelt.

@Lock(LockModeType.PESSIMISTIC_WRITE) 
@QueryHints({@QueryHint(name = "javax.persistence.lock.timeout", value   ="5000")}) 
Customer findByCustomerId(Long customerId);
1
arpit garg