Exception de verrouillage optimiste JPA dans le développement Java
Cet article explique la technologie JPA et son utilisation dans le développement Java. Des experts du développement Java en Inde expliquent le cas d'utilisation des technologies - JPA et Hibernate, base de données MySql, Maven. Lisez cet article et sachez ce qu'ils veulent dire.
Technology: JPA signifie Java Persistence API qui est le standard de Sun Micro Systems pour la persistance. ORM signifie Cartographie relationnelle d'objets. JPA est la norme pour ORM. Si un framework doit dire ORM, il doit implémenter toutes les spécifications données par JPA. JPA est juste une spécification, il a besoin de persistance pour les opérations CRUD. Hibernate, lien Eclipse, etc. Sont des exemples de fournisseurs de persistance.
Base de donnéesTechnologies: JPA et Hibernate, Maven, MySql
Usecase: Si vous travaillez sur des applications de développement Java avec JPA, hibernate, lien eclipse, vous obtiendrez souvent une exception ci-dessous:
javax.persistence.OptimisticLockException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect).
Le problème est qu'un fournisseur de persistance JPA tente de mettre à jour l'objet qui n'est pas la dernière version de l'objet. En général, les bases de données relationnelles conservent la version chaque fois qu'un enregistrement est mis à jour dans la table. Si vous souhaitez mettre à jour l'enregistrement dans la table, vous devez prendre le dernier enregistrement de version de la base de données et le mettre à jour. Comme nous utilisons ORM, nous devons prendre le dernier objet de version et le fusionner.
Ainsi, dans ce document, nous pouvons voir quand cette erreur se produit et comment la résoudre.
1. Structure du projet
La structure du projet sera comme la capture d'écran ci-dessus.
Si vous regardez la structure du projet, c'est un projet mavenpom.xml
est le fichier obligatoire. Dans ce fichier maven, nous pouvons configurer des dépendances pour jpa, hibernate, java, base de données, etc. J'utilise la base de données MySQL pour le stockage de données.
Trois packages, un pour l'entité, un pour la logique métier, un pour les tests d'application. Si vous observez qu'il existe un package DTO, si vous travaillez sur des entités d'application à plusieurs niveaux, elles ne seront pas directement exposées à la couche client. L'entité sera convertie en DTO (Data Transfer Object) qui sera mappée aux entités.
2. Dépendances du projet
pom.xml
4.0.0 naveen.examples jpa 0.0.1-SNAPSHOT jar jpa http://maven.apache.org UTF-8 1.8 4.3.6.Final UTF-8 org.hibernate hibernate-entitymanager ${hibernate.version} org.hibernate hibernate-c3p0 ${hibernate.version} mysql mysql-connector-java 5.1.31 junit junit 3.8.1 test
3. Configuration JPA
Comme il s'agit de dépendances d'hibernation ajoutées à Hibernate, s'il s'agit d'un autre ORM, ajoutez ces dépendances.
persistence.xml
org.hibernate.jpa.HibernatePersistenceProvider
Il s'agit despersistence.xml
, ici nous devons mentionner les informations d'identification de la base de données, le nom de persistance, tous les attributs requis par la fabrique du gestionnaire d'entités.
4. CRUD
C'est la classe d'entité qui va persister dans la base de données.
EmployeeBE.java
// Import statements @NamedQueries({ @NamedQuery(name = EmployeeBE.FIND_ALL, query = "SELECT e FROM EmployeeBE e order by e.name "), }) @Entity @Table(name = "T_EMP") public class EmployeeBE implements Serializable{ private static final long serialVersionUID = 1607726899931733607L; public static final String FIND_ALL = "naveen.examples.jpa.entity.EmployeeBE.find_all"; @Id @GeneratedValue(strategy = GenerationType.AUTO) private int id; @Column(name = "NAME") private String name; @Column(name = "version_num") @Version private int version; // Getters and setters }
EmployeeCrud.java
// Interface for CRUD operations. package naveen.examples.jpa.business; import java.util.List; import naveen.examples.jpa.entity.EmployeeBE; public interface EmployeeCrud { ListfindAllEmployeeBECol(); EmployeeBE saveEmployee(EmployeeBE employeeBE); EmployeeBE updateEmployee(EmployeeBE employeeBE); EmployeeBE findById(int id); }
EmployeeCrudImpl.java
// Implementatino class for CRUD operations public class EmployeeCrudImpl implements EmployeeCrud{ public EmployeeBE saveEmployee(EmployeeBE employeeBE) { EntityManager em = EntityManagerUtil.getEntityManager(); em.getTransaction().begin(); em.persist(employeeBE); em.getTransaction().commit(); return employeeBE; } public EmployeeBE updateEmployee(EmployeeBE employeeBE) { EntityManager em = EntityManagerUtil.getEntityManager(); em.getTransaction().begin(); em.merge(employeeBE); em.getTransaction().commit(); return employeeBE; } @SuppressWarnings("unchecked") public ListfindAllEmployeeBECol() { EntityManager em = EntityManagerUtil.getEntityManager(); Query query = em.createNamedQuery(EmployeeBE.FIND_ALL); return query.getResultList(); } public EmployeeBE findById(int id) { EntityManager em = EntityManagerUtil.getEntityManager(); return em.find(EmployeeBE.class, id); }
EntityManagerUtil.java
// Entity Manager public class EntityManagerUtil { private static EntityManager entityManager; private EntityManagerUtil() { } public static EntityManager getEntityManager() { if(entityManager==null){ EntityManagerFactory emFactory = Persistence.createEntityManagerFactory("jpa-example"); return emFactory.createEntityManager(); } return entityManager; } }
Si vous regardez les extraits de code ci-dessus, nous avons
-
Interface, définit les méthodes commerciales
-
InterfaceImpl, implémentation de méthodes métiers
-
EntityManagerUtility, pour obtenir l'objet du gestionnaire d'entité.
Dans la classeEntityManagerUtil
, nous transmettons le paramètre jpa-example que nous mentionnons dans le fichierpersistence.xml
, afin qu'il se connecte à cette unité de persistance.
5. DEMO
Montrez comment frapper l'exception de verrouillage optimiste JPA.
Application.java
public class Application { public static void main(String args[]) { EmployeeCrud employeeCrud = new EmployeeCrudImpl(); ListemployeeBEs = employeeCrud.findAllEmployeeBECol(); if(!employeeBEs.isEmpty()){ EmployeeBE employeeBE = employeeBEs.get(0); employeeBE.setName("Updated"); employeeCrud.updateEmployee(employeeBE); // Here Optimistic lock exception employeeCrud.updateEmployee(employeeBE); }else{ EmployeeBE employeeBE = new EmployeeBE(); employeeBE.setName("Naveen"); employeeBE = employeeCrud.saveEmployee(employeeBE); } }
Avant d'exécuter l'application, il n'y a pas de données dans DB
Si vous exécutez l'application
Si vous observez qu'il y a des données dans le tableau avec l'ID 16 et la version 0.
Maintenant, si vous exécutez l'application en mode débogage
Si vous constatez que la première mise à jour est terminée, mais qu'il y a le même objet employé dans le code, comme la première méthode de mise à jour est terminée, elle est déjà validée et la version devient 1.
Si vous observez la capture d'écran, la version est devenue 1 mais l'objet est l'ancien qui signifie avec la version 0. Maintenant, si la deuxième méthode de mise à jour est exécutée avec un ancien objet, vous obtiendrez une exception de verrouillage optimiste.
Si vous poursuivez l'exécution, il en résulte une exception de verrouillage optimiste.
6. Solution
Pour résoudre cette erreur, nous avons deux méthodes:
-
Récupérez le dernier objet de la base de données et définissez les anciennes valeurs d'objet si vous souhaitez que ces valeurs soient conservées dans le nouvel objet et fusionner.
-
Pour l'ancien objet, définissez la dernière version de Database.
Je suis la deuxième approche, si vous voyez une capture d'écran, je règle le dernier numéro de version sur l'ancien objet
Après exécution dans la console, aucune erreur:
Il s'agit de la requête SQL générée pour la deuxième méthode de mise à jour. Donc, l'exception ne s'est pas produite.
Les experts deJava development India ont partagé leurs meilleures connaissances sur la technologie JPA et son utilisation dans le projet java. If you need more details, you can ask the developers who are already applying this technology in their projects.
Conclusion
En utilisant ces deux méthodes, vous pouvez résoudre cette erreur assez ennuyeuse. Comme il s'agit d'un exemple très simple, vous pouvez le trouver facilement, mais dans une application en temps réel, vous ne trouverez pas cela aussi simple. Ainsi, chaque fois que vous obtenez cette exception, exécutez l'application en mode débogage et accédez à l'extrait de code approximatif où elle s'affiche, puis appuyez sur F5 lors du débogage et entrez dans l'implémentation du gestionnaire d'entités du fournisseur de persistance correspondant ailleurs où votre entité est mise à jour. Suivez ensuite eithr4 de ces deux techniques en fonction de vos besoins. Continuez à vérifier le numéro de version dans la base de données. Pour chaque changement, ils peuvent augmenter ou non en fonction de l'implémentation du fournisseur de persistance.