Pour Spring Data 1.6 ou supérieur
@Lock
est pris en charge sur les méthodes CRUD à partir de la version 1.6 de Spring Data JPA (en fait, il existe déjà un jalon
disponible). Voir ce ticket
pour plus de détails.
Avec cette version, vous déclarez simplement ce qui suit :
interface WidgetRepository extends Repository<Widget, Long> {
@Lock(LockModeType.PESSIMISTIC_WRITE)
Widget findOne(Long id);
}
Cela amènera la partie implémentation CRUD du proxy du référentiel de sauvegarde à appliquer le LockModeType configuré au find(…)
appeler le EntityManager
.
D'autre part,
Pour la version précédente de Spring Data 1.6
Le pessimiste de Spring Data @Lock
les annotations ne s'appliquent (comme vous l'avez souligné) qu'aux requêtes. Il n'y a pas d'annotations que je connaisse qui puissent affecter une transaction entière. Vous pouvez soit créer un findByOnePessimistic
méthode qui appelle findByOne
avec un verrou pessimiste ou vous pouvez changer findByOne
pour toujours obtenir une serrure pessimiste.
Si vous vouliez implémenter votre propre solution, vous le pourriez probablement. Sous le capot le @Lock
l'annotation est traitée par LockModePopulatingMethodIntercceptor
qui fait ce qui suit :
TransactionSynchronizationManager.bindResource(method, lockMode == null ? NULL : lockMode);
Vous pourriez créer un gestionnaire de verrouillage statique qui avait un ThreadLocal<LockMode>
membre variable et ensuite avoir un aspect enroulé autour de chaque méthode dans chaque référentiel qui a appelé bindResource avec le mode de verrouillage défini dans le ThreadLocal. Cela vous permettrait de définir le mode de verrouillage sur une base par thread. Vous pouvez alors créer votre propre @MethodLockMode
annotation qui envelopperait la méthode dans un aspect qui définit le mode de verrouillage spécifique au thread avant d'exécuter la méthode et l'efface après l'exécution de la méthode.
Lien vers la ressource :
- Comment activer LockModeType.PESSIMISTIC_WRITE lors de la recherche d'entités avec Spring Data JPA ?
- Comment ajouter une méthode personnalisée méthode à Spring Data JPA
- Délai de verrouillage pessimiste des données Spring avec Postgres
- API de requête JPA
Divers exemples de délai d'attente de verrouillage pessimiste
Configuration d'un verrou pessimiste
Un objet entité peut être verrouillé explicitement par la méthode lock :
em.lock(employee, LockModeType.PESSIMISTIC_WRITE);
Le premier argument est un objet entité. Le deuxième argument est le mode de verrouillage demandé.
Une TransactionRequiredException
est lancé s'il n'y a pas de transaction active lorsque le verrou est appelé car le verrouillage explicite nécessite une transaction active.
Une LockTimeoutException
est levée si le verrou pessimiste demandé ne peut pas être accordé :
- Un
PESSIMISTIC_READ
la demande de verrouillage échoue si un autre utilisateur (qui est représenté par une autre instance EntityManager) détient actuellement unPESSIMISTIC_WRITE
verrouille cet objet de base de données. - Un
PESSIMISTIC_WRITE
la demande de verrouillage échoue si un autre utilisateur détient actuellement soit unPESSIMISTIC_WRITE
serrure ou unPESSIMISTIC_READ
verrouiller cet objet de base de données.
Définition de l'indicateur de requête (étendues)
Les indicateurs de requête peuvent être définis dans les portées suivantes (du global au local) :
Pour toute l'unité de persistance - en utilisant un persistence.xml
propriété :
<properties>
<property name="javax.persistence.query.timeout" value="3000"/>
</properties>
Pour une EntityManagerFactory - en utilisant createEntityManagerFacotory
méthode :
Map<String,Object> properties = new HashMap();
properties.put("javax.persistence.query.timeout", 4000);
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("pu", properties);
Pour un EntityManager - en utilisant le createEntityManager
méthode :
Map<String,Object> properties = new HashMap();
properties.put("javax.persistence.query.timeout", 5000);
EntityManager em = emf.createEntityManager(properties);
ou en utilisant la méthode setProperty :
em.setProperty("javax.persistence.query.timeout", 6000);
Pour une named query
définition - en utilisant les hints
élément :
@NamedQuery(name="Country.findAll", query="SELECT c FROM Country c",
hints={@QueryHint(name="javax.persistence.query.timeout", value="7000")})
Pour une exécution de requête spécifique - en utilisant le setHint
méthode (avant l'exécution de la requête) :
query.setHint("javax.persistence.query.timeout", 8000);