Voor Spring Data 1.6 of hoger
@Lock
wordt ondersteund op CRUD-methoden vanaf versie 1.6 van Spring Data JPA (in feite is er al een mijlpaal
verkrijgbaar). Bekijk dit ticket
voor meer details.
Met die versie verklaart u eenvoudig het volgende:
interface WidgetRepository extends Repository<Widget, Long> {
@Lock(LockModeType.PESSIMISTIC_WRITE)
Widget findOne(Long id);
}
Dit zorgt ervoor dat het CRUD-implementatiegedeelte van de backing repository-proxy het geconfigureerde LockModeType toepast op de find(…)
bel de EntityManager
.
Aan de andere kant,
Voor de vorige versie van Spring Data 1.6
De pessimistische lentegegevens @Lock
annotaties zijn alleen van toepassing (zoals u opmerkte) op query's. Er zijn geen annotaties die ik ken die van invloed kunnen zijn op een hele transactie. U kunt een findByOnePessimistic
. maken methode die findByOne
. aanroept met een pessimistisch slotje of je kunt findByOne
. veranderen om altijd een pessimistisch slot te krijgen.
Als u uw eigen oplossing wilde implementeren, zou u dat waarschijnlijk kunnen. Onder de motorkap de @Lock
annotatie wordt verwerkt door LockModePopulatingMethodIntercceptor
die het volgende doet:
TransactionSynchronizationManager.bindResource(method, lockMode == null ? NULL : lockMode);
Je zou een statische vergrendelingsmanager kunnen maken met een ThreadLocal<LockMode>
member-variabele en vervolgens een aspect hebben dat om elke methode in elke repository wordt gewikkeld die bindResource aanroept met de vergrendelingsmodus ingesteld in de ThreadLocal. Hiermee kunt u de vergrendelingsmodus per thread instellen. U kunt dan uw eigen @MethodLockMode
. maken annotatie die de methode zou omwikkelen in een aspect dat de threadspecifieke vergrendelingsmodus instelt voordat de methode wordt uitgevoerd en deze wist nadat de methode is uitgevoerd.
Bronlink:
- Hoe LockModeType.PESSIMISTIC_WRITE inschakelen bij het opzoeken van entiteiten met Spring Data JPA?
- Aangepast toevoegen methode om gegevens JPA te ontspringen
- Spring Data Pessimistic Lock-time-out met Postgres
- JPA-query-API
Diverse voorbeelden van pessimistische vergrendelingstime-out
Een pessimistisch slot instellen
Een entiteitsobject kan expliciet worden vergrendeld met de lock-methode:
em.lock(employee, LockModeType.PESSIMISTIC_WRITE);
Het eerste argument is een entiteitsobject. Het tweede argument is de gevraagde vergrendelingsmodus.
Een TransactionRequiredException
wordt gegenereerd als er geen actieve transactie is wanneer vergrendeling wordt aangeroepen, omdat expliciete vergrendeling een actieve transactie vereist.
Een LockTimeoutException
wordt gegooid als het gevraagde pessimistische slot niet kan worden verleend:
- Een
PESSIMISTIC_READ
lock-verzoek mislukt als een andere gebruiker (die wordt vertegenwoordigd door een andere instantie van EntityManager) momenteel eenPESSIMISTIC_WRITE
heeft lock op dat database-object. - Een
PESSIMISTIC_WRITE
vergrendelingsverzoek mislukt als een andere gebruiker momenteel eenPESSIMISTIC_WRITE
. heeft slot of eenPESSIMISTIC_READ
vergrendel dat database-object.
Query-hint (bereik) instellen
Query-hints kunnen worden ingesteld in de volgende bereiken (van globaal tot lokaal):
Voor de gehele persistentie-eenheid - met behulp van een persistence.xml
eigendom:
<properties>
<property name="javax.persistence.query.timeout" value="3000"/>
</properties>
Voor een EntityManagerFactory - met behulp van de createEntityManagerFacotory
methode:
Map<String,Object> properties = new HashMap();
properties.put("javax.persistence.query.timeout", 4000);
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("pu", properties);
Voor een EntityManager - met behulp van de createEntityManager
methode:
Map<String,Object> properties = new HashMap();
properties.put("javax.persistence.query.timeout", 5000);
EntityManager em = emf.createEntityManager(properties);
of met behulp van de setProperty-methode:
em.setProperty("javax.persistence.query.timeout", 6000);
Voor een named query
definitie - met behulp van de hints
element:
@NamedQuery(name="Country.findAll", query="SELECT c FROM Country c",
hints={@QueryHint(name="javax.persistence.query.timeout", value="7000")})
Voor een specifieke query-uitvoering - met behulp van de setHint
methode (vóór uitvoering van de query):
query.setHint("javax.persistence.query.timeout", 8000);