#java #hibernate #jakarta-ee #concurrency
#java #переход в спящий режим #джакарта-ee #параллелизм
Вопрос:
Я просто экспериментирую с оптимистичной блокировкой.
У меня есть следующий класс:
@Entity
public class Student {
private Integer id;
private String firstName;
private String lastName;
private Integer version;
@Version
public Integer getVersion() {
return version;
}
//all other getters ommited.
}
теперь я выбираю одного из учеников и пытаюсь одновременно обновить его свойства.
Thread t1 = new Thread(new MyRunnable(id));
Thread t2 = new Thread(new MyRunnable(id));
t1.start();
t2.start();
и внутри MyRunnable:
public class MyRunnable implements Runnable {
private Integer id;
@Override
public void run() {
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Student student = (Student) session.load(Student.class, id);
student.setFirstName("xxxx");
session.save(student);
session.getTransaction().commit();
System.out.println("Done");
}
public MyRunnable(Integer id){
this.id = id;
}
}
что происходит, что первая транзакция успешно обновляет объект, а вторая транзакция выдает:
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.vanilla.entity.Student#1]
Это нормально.
Мой вопрос: 1) Что мне делать, если я хочу, чтобы вторая транзакция ничего не делала и не создавала никаких исключений.
2) Что мне делать, если я хочу, чтобы вторая транзакция переопределяла данные, обновленные первой транзакцией.
Спасибо.
Ответ №1:
Я попробую ответить на ваши вопросы:
-
Вы используете оптимистичную блокировку. Итак, вы хотите, чтобы an
OptimisticLockException
вызывался при конфликте версий, но вы можете перехватить его и ничего не делать. Вы не можете отключить его на вторую (что бы это ни значило) транзакцию, потому что вы не знаете, возникнет ли конфликт версий (в этом суть стратегии оптимистичной блокировки: оптимистичное предположение состоит в том, что конфликт версий не будет возникать очень часто) -
Если
OptimisticLockException
происходит, у вас в основном есть 2 варианта:- отмените изменения (и, возможно, обновите текущее состояние)
- обновите только версию вашего объекта (объектов) и повторите попытку фиксации
Проблема в том, как или кто должен решить, какое состояние является фактическим «правильным» (означает последнее), если у вас есть одновременные обновления. Пока согласованность гарантирована, мне было бы все равно.
Ответ №2:
Отказ от ответственности: это предложение; Я сам не пробовал.
Я бы полностью отказался от поля версии и установил для этой оптимистичной стратегии блокировки объекта значение «нет» в сопоставлении XML:
<class name="Student" optimistic-lock="none"/>
или как аннотация:
@Entity(optimisticLock=OptimisticLockType.NONE)
Они специфичны для гибернации, вы не найдете их в спецификации JPA.
Ответ №3:
У меня было такое же исключение. Это было решено, как только я изменил
@GeneratedValue(strategy = GenerationType.SEQUENCE)
Для
@GeneratedValue(strategy = GenerationType.AUTO)
в моей сущности.
Мое приложение работает на сервере MySQL.