For Spring Data 1.6 eller nyere
@Lock
er understøttet på CRUD-metoder fra version 1.6 af Spring Data JPA (faktisk er der allerede en milepæl
ledig). Se denne billet
for flere detaljer.
Med den version erklærer du blot følgende:
interface WidgetRepository extends Repository<Widget, Long> {
@Lock(LockModeType.PESSIMISTIC_WRITE)
Widget findOne(Long id);
}
Dette vil få CRUD-implementeringsdelen af backup-repository-proxyen til at anvende den konfigurerede LockModeType på find(…)
ring til EntityManager
.
På den anden side,
Til tidligere version af Spring Data 1.6
The Spring Data pessimistiske @Lock
anmærkninger gælder kun (som du påpegede) for forespørgsler. Der er ingen annoteringer, jeg kender, som kan påvirke en hel transaktion. Du kan enten oprette en findByOnePessimistic
metode, der kalder findByOne
med en pessimistisk lås, eller du kan ændre findByOne
for altid at opnå en pessimistisk lås.
Hvis du ville implementere din egen løsning, kunne du sandsynligvis. Under hætten @Lock
annotering behandles af LockModePopulatingMethodIntercceptor
som gør følgende:
TransactionSynchronizationManager.bindResource(method, lockMode == null ? NULL : lockMode);
Du kunne oprette en eller anden statisk låsemanager, som havde en ThreadLocal<LockMode>
medlemsvariabel og derefter have et aspekt pakket rundt om hver metode i hvert lager, som kaldes bindResource med låsetilstanden indstillet i ThreadLocal. Dette vil give dig mulighed for at indstille låsetilstanden på en per-tråd basis. Du kan derefter oprette din egen @MethodLockMode
annotation, som ville omslutte metoden i et aspekt, der indstiller den trådspecifikke låsetilstand, før metoden køres, og rydder den efter kørsel af metoden.
Ressourcelink:
- Hvordan aktiverer du LockModeType.PESSIMISTIC_WRITE, når du slår enheder op med Spring Data JPA?
- Sådan tilføjer du tilpasset metode til Spring Data JPA
- Timeout for Spring Data Pessimistic Lock med Postgres
- JPA Query API
Forskellige eksempler på pessimistisk låsetimeout
Indstilling af en pessimistisk lås
Et entitetsobjekt kan låses eksplicit ved hjælp af låsemetoden:
em.lock(employee, LockModeType.PESSIMISTIC_WRITE);
Det første argument er et entitetsobjekt. Det andet argument er den ønskede låsetilstand.
En TransactionRequiredException
kastes, hvis der ikke er nogen aktiv transaktion, når låsen kaldes, fordi eksplicit låsning kræver en aktiv transaktion.
En LockTimeoutException
kastes, hvis den ønskede pessimistiske lås ikke kan tildeles:
- En
PESSIMISTIC_READ
låseanmodning mislykkes, hvis en anden bruger (som er repræsenteret af en anden EntityManager-instans) i øjeblikket har enPESSIMISTIC_WRITE
lås på det databaseobjekt. - En
PESSIMISTIC_WRITE
låseanmodning mislykkes, hvis en anden bruger i øjeblikket har enten enPESSIMISTIC_WRITE
lås eller enPESSIMISTIC_READ
lås på databaseobjektet.
Indstilling af forespørgselstip (omfang)
Forespørgselstip kan indstilles i følgende omfang (fra globalt til lokalt):
For hele persistensenheden - ved hjælp af en persistence.xml
ejendom:
<properties>
<property name="javax.persistence.query.timeout" value="3000"/>
</properties>
For en EntityManagerFactory - ved hjælp af createEntityManagerFacotory
metode:
Map<String,Object> properties = new HashMap();
properties.put("javax.persistence.query.timeout", 4000);
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("pu", properties);
For en EntityManager - ved hjælp af createEntityManager
metode:
Map<String,Object> properties = new HashMap();
properties.put("javax.persistence.query.timeout", 5000);
EntityManager em = emf.createEntityManager(properties);
eller ved at bruge setProperty-metoden:
em.setProperty("javax.persistence.query.timeout", 6000);
For en named query
definition - ved hjælp af hints
element:
@NamedQuery(name="Country.findAll", query="SELECT c FROM Country c",
hints={@QueryHint(name="javax.persistence.query.timeout", value="7000")})
Til en specifik forespørgselsudførelse - ved hjælp af setHint
metode (før udførelse af forespørgsel):
query.setHint("javax.persistence.query.timeout", 8000);