Dans mon application - Oracle avec JPA (EclipseLink), j'utilise l'expression suivante pour verrouiller le sous-ensemble des enregistrements dans certaines tables:
select * from MY_TABLE where MY_CONDITIONS for update skip locked
Je l'exécute tout au long de la requête native, mais je dois écrire cette requête pour toutes les entités requises.
Existe-t-il un moyen d'éviter les enregistrements verrouillés à l'aide de JPA pur? Puis-je mettre en œuvre ma propre politique de verrouillage?
Cela ne me dérange pas de changer de fournisseur JPA, mais je souhaite utiliser l'API JPA.
Hibernate fournit le mode de verrouillage UPGRADE_SKIPLOCKED.
Avec JPA et Hibernate, pour produire un "SKIP_LOCKED" conformément à Hibernate LockMode documentation, vous devez combiner le PESSIMISTIC_WRITE JPA LockModeType :
entityManager.find(Department.class, 1, LockModeType.PESSIMISTIC_WRITE);
et le paramètre Délai de verrouillage, comme par exemple dans persistence.xml pour votre unité de persistance:
<properties>
<property name="javax.persistence.query.timeout" value="-2"/>
</properties>
(Notez que vous pouvez également configurer ce LockMode pour une requête complexe)
SKIP LOCKED ne fait pas partie de ANSI SQL. Certains SGBDR tels que ceux-ci fournissent ceci comme une fonctionnalité spécifique:
Donc, avec JPA pur, il n'est pas possible de spécifier un "SKIP LOCKED" dans les requêtes . En effet, comme indiqué dans LockModeType , JPA 2.1 prend uniquement en charge les éléments suivants:
Cependant, pour activer SKIP LOCKED dans votre requête, vous pouvez utiliser ces alternatives:
Je sais que ce message est un peu vieux, mais pour mémoire, comme indiqué dans la réponse acceptée, "javax.persistence.lock.timeout" a la valeur "-2" avec les résultats d'Hibernate dans "SKIP LOCKED". Toutefois, cela peut être fait au moment de l'exécution sans avoir à définir de paramètres globaux.
Depuis 2.0 JPA permet de transmettre des astuces long comme si
entityManager.find(MyType.class, id, LockModeType.PESSIMISTIC_WRITE, new HashMap<String, Object>() {{
put("javax.persistence.lock.timeout", "-2");
}});
Oracle ne fournit pas de verrou de lecture, car il n'en a pas besoin. les journaux d'annulation rendent cela inutile. Donc, SELECT ... FOR UPDATE n’est en réalité qu’un verrou WRITE pour Oracle.
Avec JPA, vous souhaitez définir LockModeType en tant que PESSIMISTIC_WRITE.