Исключение оптимистической блокировки JPA в разработке на Java
В этом посте объясняется технология JPA и ее использование при разработке Java. Специалисты в области разработки Java-приложений Индии объясняют вариант использования технологий - JPA и Hibernate, MySql database, Maven. Прочтите этот пост и знайте, что они хотят сказать.
Technology: JPA обозначает Java Persistence API, который является стандартом Sun Micro Systems для сохранения состояния. ORM означает реляционное отображение объектов. JPA - это стандарт ORM. Если фреймворк должен использовать ORM, он должен реализовывать все спецификации, предоставленные JPA. JPA - это просто спецификация, она требует постоянства для операций CRUD. Hibernate, ссылка Eclipse и т. Д. Являются примером поставщиков персистентности.
Technologies: JPA и база данных Hibernate, Maven, MySql
Usecase: Если вы работаете над приложениями для разработки Java с помощью JPA, hibernate, eclipse, вы часто будете получать исключение ниже:
javax.persistence.OptimisticLockException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect).
Проблема в том, что поставщик сохраняемости JPA пытается обновить объект, который не является объектом последней версии. Обычно реляционные базы данных поддерживают версию всякий раз, когда в таблице обновляется запись. Если вы хотите обновить запись в таблице, вы должны взять последнюю версию записи из базы данных и обновить ее. Поскольку мы используем ORM, мы должны взять объект последней версии и объединить его.
Итак, в этом документе мы можем увидеть, когда возникает эта ошибка и как ее решить.
1. Структура проекта
Структура проекта будет такой, как на скриншоте выше.
Если вы посмотрите на структуру проекта, то увидите, что проект mavenpom.xml
является обязательным файлом it. В этом файле maven мы можем настроить зависимости для jpa, hibernate, java, database и т. Д. Я использую базу данных MySQL для хранения данных.
Три пакета: один для сущности, один для бизнес-логики, один для тестирования приложений. Если вы заметите, что существует один пакет DTO, если вы работаете с многоуровневыми объектами приложения, они не будут напрямую отображаться на клиентском уровне. Сущность будет преобразована в DTO (объект передачи данных), который будет сопоставлен с сущностями.
2. Зависимости проекта
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
Поскольку это Hibernate, добавленные зависимости hibernate, если это какой-то другой ORM, добавьте эти зависимости.
persistence.xml
org.hibernate.jpa.HibernatePersistenceProvider
Этоpersistence.xml
, здесь нам нужно указать учетные данные базы данных, имя постоянства, все необходимые атрибуты фабрики диспетчера сущностей.
4. CRUD
Это класс сущности, который будет сохраняться в базе данных.
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; } }
Если вы посмотрите на приведенные выше фрагменты кода, у нас есть
-
Интерфейс, определяет бизнес-методы
-
InterfaceImpl, реализация бизнес-методов
-
EntityManagerUtility, чтобы получить объект менеджера сущностей.
В классеEntityManagerUtil
мы передаем параметр jpa-example, который мы упоминаем в файлеpersistence.xml
, поэтому он будет подключаться к этому блоку сохранения состояния.
5. DEMO
Продемонстрируйте, как попасть в исключение оптимистической блокировки 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); } }
Перед запуском приложения в БД нет данных
Если вы запустите приложение
Если вы заметили, что в таблице есть данные с идентификатором 16 и версией 0.
Теперь, если вы запустите приложение в режиме отладки
Если вы заметите, что первое обновление завершено, но в коде есть тот же объект-сотрудник, поскольку первый метод обновления завершился, он уже зафиксирован, поэтому версия становится 1.
Если вы посмотрите на снимок экрана, версия стала 1, но объект старый, то есть с версией 0. Теперь, если второй метод обновления выполняется со старым объектом, вы получите исключение оптимистической блокировки.
Если вы продолжите выполнение, это приведет к исключению оптимистической блокировки.
6. Решение
Чтобы устранить эту ошибку, у нас есть два способа:
-
Получите последний объект из базы данных и установите старые значения объекта, если вам нужно, чтобы эти значения были сохранены в новом объекте, и объедините его.
-
Для старого объекта установите последнюю версию из базы данных.
Я следую второму подходу. Если вы видите снимок экрана, я устанавливаю номер последней версии для старого объекта.
После выполнения в консоли ошибки нет:
Это SQL-запрос, созданный для второго метода обновления. Значит, исключения не произошло.
ЭкспертыJava development India поделились своими лучшими знаниями о технологии JPA и ее использовании в java-проекте. If you need more details, you can ask the developers who are already applying this technology in their projects.
Заключение
Используя эти два способа, вы можете решить эту досадную ошибку. Поскольку это очень простой пример, вы можете легко его найти, но в приложении реального времени вы не найдете его таким простым. Поэтому всякий раз, когда вы получаете это исключение, запустите приложение в режиме отладки и перейдите к примерному фрагменту кода, где он отображается, затем нажмите F5 при отладке и углубитесь в реализацию диспетчера сущностей соответствующего поставщика постоянства в другом месте, где ваша сущность обновляется. Затем выполните любой из этих двух методов в зависимости от ваших требований. Продолжайте проверять номер версии в базе данных. Для каждого изменения они могут увеличиваться или не увеличиваться в зависимости от реализации поставщика сохраняемости.