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_READlåseanmodning mislykkes, hvis en anden bruger (som er repræsenteret af en anden EntityManager-instans) i øjeblikket har enPESSIMISTIC_WRITElås på det databaseobjekt. - En
PESSIMISTIC_WRITElåseanmodning mislykkes, hvis en anden bruger i øjeblikket har enten enPESSIMISTIC_WRITElås eller enPESSIMISTIC_READlå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);