JPA-Ausnahme für optimistische Sperre in Java Development

JPA-optimistische Sperrausnahme in der Java-Entwicklung

In diesem Beitrag werden die JPA-Technologie und ihre Verwendung in der Java-Entwicklung erläutert. Experten der Java-Entwicklung Indien erklären den Anwendungsfall von Technologien - JPA und Hibernate, MySql-Datenbank, Maven. Lesen Sie diesen Beitrag und wissen Sie, was sie sagen wollen.

Technology: JPA steht für die Java Persistence API, die der Standard von Sun Micro Systems für Persistenz ist. ORM steht für Object Relational Mapping. JPA ist der Standard für ORM. Wenn ein Framework ORM sagen muss, sollte es alle von JPA angegebenen Spezifikationen implementieren. JPA ist nur eine Spezifikation, es muss eine Persistenz für CRUD-Operationen bereitgestellt werden. Ruhezustand, Eclipse-Link usw. Sind Beispiele für Persistenzanbieter.

Technologies: JPA- und Hibernate-, Maven-, MySql-Datenbank

Usecase: Wenn Sie an Java-Entwicklungsanwendungen mit JPA, Ruhezustand und Eclipse-Link arbeiten, wird häufig die folgende Ausnahme angezeigt:

javax.persistence.OptimisticLockException: Row was updated or deleted by another
transaction (or unsaved-value mapping was incorrect).

Das Problem ist, dass ein JPA-Persistenzanbieter versucht, das Objekt zu aktualisieren, das nicht das Objekt der neuesten Version ist. Im Allgemeinen behalten relationale Datenbanken die Version bei, wenn ein Datensatz in der Tabelle aktualisiert wird. Wenn Sie den Datensatz in der Tabelle aktualisieren möchten, sollten Sie den neuesten Versionsdatensatz aus der Datenbank entnehmen und aktualisieren. Da wir ORM verwenden, sollten wir das Objekt der letzten Version nehmen und zusammenführen.

In diesem Dokument können wir also sehen, wann dieser Fehler auftritt und wie er behoben werden kann.

1. Projektstruktur

jpa-lock-project-structure

Die Projektstruktur entspricht dem obigen Screenshot.

Wenn Sie sich die Projektstruktur ansehen, handelt es sich um ein Maven-Projekt.pom.xml ist die obligatorische Datei. In dieser Maven-Datei können wir Abhängigkeiten für JPA, Ruhezustand, Java, Datenbank usw. konfigurieren. Ich verwende die MySQL-Datenbank zur Datenspeicherung.

Drei Pakete, eines für die Entität, eines für die Geschäftslogik und eines für das Testen von Anwendungen. Wenn Sie feststellen, dass es ein DTO-Paket gibt, werden bei der Arbeit an mehrschichtigen Anwendungsentitäten die Client-Schicht nicht direkt verfügbar gemacht. Die Entität wird in DTO (Data Transfer Object) konvertiert, das Entitäten zugeordnet wird.

2. Projektabhängigkeiten

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. JPA-Konfiguration

Da es sich um Ruhezustände handelt, wurden Ruhezustandsabhängigkeiten hinzugefügt. Wenn es sich um ein anderes ORM handelt, fügen Sie diese Abhängigkeiten hinzu.

persistence.xml



    
        org.hibernate.jpa.HibernatePersistenceProvider
        
            
            
            
            
            
            
            
            
            
            
            
            
            
            
        
    

Dies istpersistence.xml. Hier müssen die Datenbankanmeldeinformationen, der Persistenzname und alle erforderlichen Attribute der Entity Manager-Factory angegeben werden.

4. CRUD

Dies ist die Entitätsklasse, die in der Datenbank bestehen bleibt.

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;
    }
}

Wenn Sie sich die obigen Codefragmente ansehen, haben wir sie

  1. Schnittstelle, definiert Geschäftsmethoden

  2. InterfaceImpl, Implementierung von Geschäftsmethoden

  3. EntityManagerUtility, um das Entity Manager-Objekt abzurufen.

In der KlasseEntityManagerUtilübergeben wir den Parameter jpa-example, den wir in der Dateipersistence.xmlerwähnen, damit eine Verbindung zu dieser Persistenzeinheit hergestellt wird.

5. DEMO

Zeigen Sie, wie Sie die optimistische JPA-Sperrausnahme treffen.

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

Vor dem Ausführen der App befinden sich keine Daten in der Datenbank

jpa-lock-screen-2

Wenn Sie die Anwendung ausführen

jpa-lock-screen-3

jpa-lock-screen-4

Wenn Sie feststellen, dass die Tabelle Daten mit der ID 16 und der Version 0 enthält.

Nun, wenn Sie die Anwendung im Debug-Modus ausführen

jpa-lock-screen-5

Wenn Sie feststellen, dass die erste Aktualisierung abgeschlossen wurde, der Code jedoch dasselbe Mitarbeiterobjekt enthält, wurde die erste Aktualisierungsmethode bereits festgeschrieben, sodass die Version 1 wird.

jpa-lock-screen-6

Wenn Sie den Screenshot betrachten, wurde die Version 1, aber das Objekt ist das alte, dh mit Version 0. Wenn nun die zweite Aktualisierungsmethode mit einem alten Objekt ausgeführt wird, erhalten Sie eine optimistische Sperrausnahme.

jpa-lock-screen-7

Wenn Sie die Ausführung fortsetzen, führt dies zu einer optimistischen Sperrausnahme.

6. Lösung

Um diesen Fehler zu beheben, haben wir zwei Möglichkeiten:

  1. Holen Sie sich das neueste Objekt aus der Datenbank und legen Sie die alten Objektwerte fest, wenn diese Werte für das neue Objekt beibehalten und zusammengeführt werden sollen.

  2. Stellen Sie für das alte Objekt die neueste Version aus der Datenbank ein.

jpa-lock-screen-8

Ich verfolge den zweiten Ansatz. Wenn Sie einen Screenshot sehen, setze ich die neueste Versionsnummer auf das alte Objekt

jpa-lock-screen-9

Nach der Ausführung in der Konsole kein Fehler:

jpa-lock-screen-10

Dies ist die SQL-Abfrage, die für die zweite Aktualisierungsmethode generiert wurde. Die Ausnahme ist also nicht aufgetreten.

Experten vonJava development Indiahaben ihr bestes Wissen über die JPA-Technologie und ihre Verwendung in Java-Projekten geteilt. If you need more details, you can ask the developers who are already applying this technology in their projects.

Fazit

Mit diesen beiden Möglichkeiten können Sie diesen ziemlich nervigen Fehler beheben. Da dies ein sehr einfaches Beispiel ist, können Sie es leicht finden, aber in der Echtzeitanwendung werden Sie es nicht so einfach finden. Wenn Sie diese Ausnahme erhalten, führen Sie die Anwendung im Debug-Modus aus und gehen Sie zu dem ungefähren Code-Snippet, in dem sie angezeigt wird. Drücken Sie dann beim Debuggen F5 und gehen Sie tief in die Entity-Manager-Implementierung des entsprechenden Persistenzanbieters ein, wo Ihre Entität gerade aktualisiert wird. Folgen Sie dann je nach Ihren Anforderungen eithr4 dieser beiden Techniken. Überprüfen Sie weiterhin die Versionsnummer in der Datenbank. Für jede Änderung können sie sich basierend auf der Implementierung des Persistenzanbieters erhöhen oder nicht.