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
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 { 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; } }
Wenn Sie sich die obigen Codefragmente ansehen, haben wir sie
-
Schnittstelle, definiert Geschäftsmethoden
-
InterfaceImpl, Implementierung von Geschäftsmethoden
-
EntityManagerUtility, um das Entity Manager-Objekt abzurufen.
In der KlasseEntityManagerUtil
übergeben wir den Parameter jpa-example, den wir in der Dateipersistence.xml
erwä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(); 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); } }
Vor dem Ausführen der App befinden sich keine Daten in der Datenbank
Wenn Sie die Anwendung ausführen
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
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.
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.
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:
-
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.
-
Stellen Sie für das alte Objekt die neueste Version aus der Datenbank ein.
Ich verfolge den zweiten Ansatz. Wenn Sie einen Screenshot sehen, setze ich die neueste Versionsnummer auf das alte Objekt
Nach der Ausführung in der Konsole kein Fehler:
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.