Exception de verrouillage optimiste JPA dans le développement Java

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

jpa-lock-project-structure

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 {

    List findAllEmployeeBECol();

    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 List findAllEmployeeBECol() {
        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

  1. Interface, définit les méthodes commerciales

  2. InterfaceImpl, implémentation de méthodes métiers

  3. 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();

        List employeeBEs = 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);
        }
    }

jpa-lock-screen-1

Avant d'exécuter l'application, il n'y a pas de données dans DB

jpa-lock-screen-2

Si vous exécutez l'application

jpa-lock-screen-3

jpa-lock-screen-4

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

jpa-lock-screen-5

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.

jpa-lock-screen-6

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.

jpa-lock-screen-7

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:

  1. 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.

  2. Pour l'ancien objet, définissez la dernière version de Database.

jpa-lock-screen-8

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

jpa-lock-screen-9

Après exécution dans la console, aucune erreur:

jpa-lock-screen-10

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.