Исключение оптимистической блокировки JPA в Java Development

Исключение оптимистической блокировки 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. Структура проекта

jpa-lock-project-structure

Структура проекта будет такой, как на скриншоте выше.

Если вы посмотрите на структуру проекта, то увидите, что проект 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 {

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

Если вы посмотрите на приведенные выше фрагменты кода, у нас есть

  1. Интерфейс, определяет бизнес-методы

  2. InterfaceImpl, реализация бизнес-методов

  3. EntityManagerUtility, чтобы получить объект менеджера сущностей.

В классеEntityManagerUtil мы передаем параметр jpa-example, который мы упоминаем в файлеpersistence.xml, поэтому он будет подключаться к этому блоку сохранения состояния.

5. DEMO

Продемонстрируйте, как попасть в исключение оптимистической блокировки 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

Перед запуском приложения в БД нет данных

jpa-lock-screen-2

Если вы запустите приложение

jpa-lock-screen-3

jpa-lock-screen-4

Если вы заметили, что в таблице есть данные с идентификатором 16 и версией 0.

Теперь, если вы запустите приложение в режиме отладки

jpa-lock-screen-5

Если вы заметите, что первое обновление завершено, но в коде есть тот же объект-сотрудник, поскольку первый метод обновления завершился, он уже зафиксирован, поэтому версия становится 1.

jpa-lock-screen-6

Если вы посмотрите на снимок экрана, версия стала 1, но объект старый, то есть с версией 0. Теперь, если второй метод обновления выполняется со старым объектом, вы получите исключение оптимистической блокировки.

jpa-lock-screen-7

Если вы продолжите выполнение, это приведет к исключению оптимистической блокировки.

6. Решение

Чтобы устранить эту ошибку, у нас есть два способа:

  1. Получите последний объект из базы данных и установите старые значения объекта, если вам нужно, чтобы эти значения были сохранены в новом объекте, и объедините его.

  2. Для старого объекта установите последнюю версию из базы данных.

jpa-lock-screen-8

Я следую второму подходу. Если вы видите снимок экрана, я устанавливаю номер последней версии для старого объекта.

jpa-lock-screen-9

После выполнения в консоли ошибки нет:

jpa-lock-screen-10

Это 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 при отладке и углубитесь в реализацию диспетчера сущностей соответствующего поставщика постоянства в другом месте, где ваша сущность обновляется. Затем выполните любой из этих двух методов в зависимости от ваших требований. Продолжайте проверять номер версии в базе данных. Для каждого изменения они могут увеличиваться или не увеличиваться в зависимости от реализации поставщика сохраняемости.

Related