Oracle
 sql >> Database >  >> RDS >> Oracle

Come specificare @lock timeout nella query jpa di dati primaverili?

Per Spring Data 1.6 o versioni successive

@Lock è supportato sui metodi CRUD a partire dalla versione 1.6 di Spring Data JPA (in effetti, esiste già un pietra miliare a disposizione). Vedi questo biglietto per maggiori dettagli.

Con quella versione dichiari semplicemente quanto segue:

interface WidgetRepository extends Repository<Widget, Long> {

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

Ciò farà sì che la parte di implementazione CRUD del proxy del repository di supporto applichi il LockModeType configurato a find(…) chiama il EntityManager .

D'altra parte,

Per la versione precedente di Spring Data 1.6

Il pessimista di Spring Data @Lock le annotazioni si applicano (come hai sottolineato) solo alle query. Non ci sono annotazioni che conosco che possono influenzare un'intera transazione. Puoi creare un findByOnePessimistic metodo che chiama findByOne con un lucchetto pessimistico oppure puoi cambiare findByOne per ottenere sempre una serratura pessimista.

Se volessi implementare la tua soluzione probabilmente potresti. Sotto il cofano il @Lock l'annotazione viene elaborata da LockModePopulatingMethodIntercceptor che fa quanto segue:

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

Potresti creare un gestore di blocco statico che avesse un ThreadLocal<LockMode> membro variabile e quindi avere un aspetto avvolto attorno a ogni metodo in ogni repository che ha chiamato bindResource con la modalità di blocco impostata in ThreadLocal. Ciò ti consentirebbe di impostare la modalità di blocco in base al thread. Puoi quindi creare il tuo @MethodLockMode annotazione che avvolgerebbe il metodo in un aspetto che imposta la modalità di blocco specifica del thread prima di eseguire il metodo e lo cancella dopo l'esecuzione del metodo.

Link alla risorsa:

  1. Come abilitare LockModeType.PESSIMISTIC_WRITE durante la ricerca di entità con Spring Data JPA?
  2. Come aggiungere elementi personalizzati metodo per Spring Data JPA
  3. Timeout del blocco pessimistico dei dati di primavera con Postgres
  4. API di query JPA

Vari esempi di timeout blocco pessimistico

Impostazione di un blocco pessimistico

Un oggetto entità può essere bloccato in modo esplicito dal metodo lock:

em.lock(employee, LockModeType.PESSIMISTIC_WRITE);

Il primo argomento è un oggetto entità. Il secondo argomento è la modalità di blocco richiesta.

Una TransactionRequiredException viene generato se non ci sono transazioni attive quando viene chiamato il blocco perché il blocco esplicito richiede una transazione attiva.

Un LockTimeoutException viene lanciato se non è possibile concedere il blocco pessimistico richiesto:

  • Un PESSIMISTIC_READ la richiesta di blocco non riesce se un altro utente (rappresentato da un'altra istanza di EntityManager) detiene attualmente un PESSIMISTIC_WRITE bloccare quell'oggetto database.
  • Un PESSIMISTIC_WRITE la richiesta di blocco non riesce se un altro utente detiene attualmente un PESSIMISTIC_WRITE lucchetto o un PESSIMISTIC_READ bloccare quell'oggetto database.

Impostazione del suggerimento query (ambito)

I suggerimenti per le query possono essere impostati nei seguenti ambiti (da globale a locale):

Per l'intera unità di persistenza, utilizzando un persistence.xml proprietà:

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

Per una EntityManagerFactory:utilizzando createEntityManagerFacotory metodo:

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

Per un EntityManager:utilizzando createEntityManager metodo:

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

o utilizzando il metodo setProperty:

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

Per una named query definizione - usando i hints elemento:

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

Per l'esecuzione di una query specifica, utilizzando il setHint metodo (prima dell'esecuzione della query):

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

Link alla risorsa:

  1. Blocco in JPA
  2. Timeout blocco pessimistico