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_READla richiesta di blocco non riesce se un altro utente (rappresentato da un'altra istanza di EntityManager) detiene attualmente unPESSIMISTIC_WRITEbloccare quell'oggetto database. - Un
PESSIMISTIC_WRITEla richiesta di blocco non riesce se un altro utente detiene attualmente unPESSIMISTIC_WRITElucchetto o unPESSIMISTIC_READbloccare 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);