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:
- Come abilitare LockModeType.PESSIMISTIC_WRITE durante la ricerca di entità con Spring Data JPA?
- Come aggiungere elementi personalizzati metodo per Spring Data JPA
- Timeout del blocco pessimistico dei dati di primavera con Postgres
- 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 unPESSIMISTIC_WRITE
bloccare quell'oggetto database. - Un
PESSIMISTIC_WRITE
la richiesta di blocco non riesce se un altro utente detiene attualmente unPESSIMISTIC_WRITE
lucchetto o unPESSIMISTIC_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);