Pro Spring Data 1.6 nebo vyšší
@Lock
je podporován na metodách CRUD od verze 1.6 Spring Data JPA (ve skutečnosti již existuje milník
dostupný). Podívejte se na tuto vstupenku
pro více podrobností.
S touto verzí jednoduše deklarujete následující:
interface WidgetRepository extends Repository<Widget, Long> {
@Lock(LockModeType.PESSIMISTIC_WRITE)
Widget findOne(Long id);
}
To způsobí, že implementační část CRUD záložního úložiště proxy použije nakonfigurovaný LockModeType na find(…)
zavolejte EntityManager
.
Na druhou stranu
Pro předchozí verzi Spring Data 1.6
Pesimistická jarní data @Lock
anotace se vztahují pouze (jak jste zdůraznil) na dotazy. Neznám žádné poznámky, které by mohly ovlivnit celou transakci. Můžete buď vytvořit findByOnePessimistic
metoda, která volá findByOne
s pesimistickým zámkem nebo můžete změnit findByOne
vždy získat pesimistický zámek.
Pokud byste chtěli implementovat své vlastní řešení, pravděpodobně byste mohli. Pod kapotou @Lock
anotace je zpracována pomocí LockModePopulatingMethodIntercceptor
který dělá následující:
TransactionSynchronizationManager.bindResource(method, lockMode == null ? NULL : lockMode);
Mohli byste vytvořit nějakého statického správce zámků, který měl ThreadLocal<LockMode>
členskou proměnnou a pak mají kolem každé metody v každém úložišti zabalený aspekt, který volá bindResource s režimem zámku nastaveným v ThreadLocal. To vám umožní nastavit režim uzamčení na základě jednotlivých vláken. Poté si můžete vytvořit svůj vlastní @MethodLockMode
anotace, která by zabalila metodu do aspektu, který nastaví režim uzamčení specifického pro vlákno před spuštěním metody a vymaže jej po spuštění metody.
Odkaz na zdroj:
- Jak povolit LockModeType.PESSIMISTIC_WRITE při vyhledávání entit pomocí Spring Data JPA?
- Jak přidat vlastní metoda Spring Data JPA
- Vypršel časový limit jarního datového pesimistického uzamčení s Postgres
- JPA Query API
Různé příklady pesimistického časového limitu uzamčení
Nastavení pesimistického zámku
Objekt entity lze zamknout explicitně metodou lock:
em.lock(employee, LockModeType.PESSIMISTIC_WRITE);
První argument je objekt entity. Druhým argumentem je požadovaný režim uzamčení.
TransactionRequiredException
je vyvoláno, pokud při volání zámku není žádná aktivní transakce, protože explicitní zamykání vyžaduje aktivní transakci.
LockTimeoutException
je vyvoláno, pokud nelze udělit požadovaný pesimistický zámek:
PESSIMISTIC_READ
požadavek na zámek selže, pokud jiný uživatel (který je zastoupen jinou instancí EntityManager) aktuálně držíPESSIMISTIC_WRITE
uzamknout tento databázový objekt.PESSIMISTIC_WRITE
požadavek na zámek selže, pokud jiný uživatel aktuálně drží buďPESSIMISTIC_WRITE
zámek neboPESSIMISTIC_READ
uzamknout tento databázový objekt.
Nastavení nápovědy pro dotaz (rozsahy)
Nápovědy pro dotazy lze nastavit v následujících rozsahech (od globálního po místní):
Pro celou jednotku persistence - pomocí persistence.xml
vlastnost:
<properties>
<property name="javax.persistence.query.timeout" value="3000"/>
</properties>
Pro EntityManagerFactory – pomocí createEntityManagerFacotory
metoda:
Map<String,Object> properties = new HashMap();
properties.put("javax.persistence.query.timeout", 4000);
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("pu", properties);
Pro EntityManager - pomocí createEntityManager
metoda:
Map<String,Object> properties = new HashMap();
properties.put("javax.persistence.query.timeout", 5000);
EntityManager em = emf.createEntityManager(properties);
nebo pomocí metody setProperty:
em.setProperty("javax.persistence.query.timeout", 6000);
Pro named query
definice - pomocí hints
prvek:
@NamedQuery(name="Country.findAll", query="SELECT c FROM Country c",
hints={@QueryHint(name="javax.persistence.query.timeout", value="7000")})
Pro provedení konkrétního dotazu - pomocí setHint
metoda (před provedením dotazu):
query.setHint("javax.persistence.query.timeout", 8000);