Dla Spring Data w wersji 1.6 lub nowszej
@Lock
jest obsługiwany w metodach CRUD od wersji 1.6 Spring Data JPA (w rzeczywistości istnieje już kamień milowy
do dyspozycji). Zobacz ten bilet
po więcej szczegółów.
W tej wersji po prostu deklarujesz, co następuje:
interface WidgetRepository extends Repository<Widget, Long> {
@Lock(LockModeType.PESSIMISTIC_WRITE)
Widget findOne(Long id);
}
Spowoduje to, że część implementacji CRUD serwera proxy repozytorium zapasowego zastosuje skonfigurowany LockModeType do find(…)
wywołaj EntityManager
.
Z drugiej strony
Dla poprzedniej wersji Spring Data 1.6
Pesymistyczne @Lock
Spring Data adnotacje dotyczą tylko (jak wskazałeś) zapytań. Nie znam adnotacji, które mogłyby wpłynąć na całą transakcję. Możesz utworzyć findByOnePessimistic
metoda, która wywołuje findByOne
z pesymistyczną blokadą lub możesz zmienić findByOne
aby zawsze uzyskać pesymistyczny zamek.
Jeśli chciałbyś wdrożyć własne rozwiązanie, prawdopodobnie mógłbyś. Pod maską @Lock
adnotacja jest przetwarzana przez LockModePopulatingMethodIntercceptor
który wykonuje następujące czynności:
TransactionSynchronizationManager.bindResource(method, lockMode == null ? NULL : lockMode);
Możesz stworzyć statycznego menedżera blokad, który miał ThreadLocal<LockMode>
zmienna członkowska, a następnie ma aspekt owinięty wokół każdej metody w każdym repozytorium, która wywołała bindResource z trybem blokady ustawionym w ThreadLocal. Umożliwiłoby to ustawienie trybu blokady na podstawie wątku. Następnie możesz stworzyć swój własny @MethodLockMode
adnotacja, która zawijałaby metodę w aspekt, który ustawia tryb blokady specyficzny dla wątku przed uruchomieniem metody i czyści go po uruchomieniu metody.
Link do zasobów:
- Jak włączyć LockModeType.PESSIMISTIC_WRITE podczas wyszukiwania jednostek za pomocą Spring Data JPA?
- Jak dodać niestandardowe metoda do Spring Data JPA
- Limit czasu blokady pesymistycznych danych wiosennych z Postgresem
- interfejs API zapytań JPA
Różne przykłady pesymistycznego limitu czasu blokady
Ustawianie pesymistycznej blokady
Obiekt encji można zablokować jawnie za pomocą metody lock:
em.lock(employee, LockModeType.PESSIMISTIC_WRITE);
Pierwszy argument to obiekt encji. Drugi argument to żądany tryb blokady.
TransactionRequiredException
jest generowany, jeśli nie ma aktywnej transakcji po wywołaniu blokady, ponieważ jawne blokowanie wymaga aktywnej transakcji.
LockTimeoutException
jest wyrzucany, jeśli żądana blokada pesymistyczna nie może zostać przyznana:
PESSIMISTIC_READ
żądanie blokady kończy się niepowodzeniem, jeśli inny użytkownik (reprezentowany przez inną instancję EntityManager) aktualnie posiadaPESSIMISTIC_WRITE
zablokować ten obiekt bazy danych.PESSIMISTIC_WRITE
żądanie blokady kończy się niepowodzeniem, jeśli inny użytkownik aktualnie posiada alboPESSIMISTIC_WRITE
zamek lubPESSIMISTIC_READ
zablokuj ten obiekt bazy danych.
Ustawianie podpowiedzi do zapytania (zakresy)
Wskazówki dotyczące zapytań można ustawić w następujących zakresach (od globalnego do lokalnego):
Dla całej jednostki trwałości - przy użyciu persistence.xml
właściwość:
<properties>
<property name="javax.persistence.query.timeout" value="3000"/>
</properties>
Dla EntityManagerFactory — przy użyciu createEntityManagerFacotory
metoda:
Map<String,Object> properties = new HashMap();
properties.put("javax.persistence.query.timeout", 4000);
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("pu", properties);
Dla EntityManager - za pomocą createEntityManager
metoda:
Map<String,Object> properties = new HashMap();
properties.put("javax.persistence.query.timeout", 5000);
EntityManager em = emf.createEntityManager(properties);
lub za pomocą metody setProperty:
em.setProperty("javax.persistence.query.timeout", 6000);
Dla named query
definicja - za pomocą hints
element:
@NamedQuery(name="Country.findAll", query="SELECT c FROM Country c",
hints={@QueryHint(name="javax.persistence.query.timeout", value="7000")})
Dla wykonania określonego zapytania - za pomocą setHint
metoda (przed wykonaniem zapytania):
query.setHint("javax.persistence.query.timeout", 8000);