Как вручную установить поля @Version в Hibernate 4? - PullRequest
9 голосов
/ 06 февраля 2012

Среда:

У меня есть User сущность:

@Entity
public class User implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer userId;

    @Version
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "VERSION", length = 19)
    private Date version;

    @Column(nullable = false, length = 20)
    private String login;

    // Getters and Setters
}

У меня есть страница поиска, на которой перечислены пользователи, затем я нажимаю на пользователя, чтобыотредактируйте его (указав userId в URL).

В форме редактирования я сохраняю на сервере поля этого объекта, и когда я сохраняю своего пользователя, я делаю это:

User user = entityManager.find(User.class, userId)
user.setLogin(form.getLogin());
user.setVersion(form.getVersion());
user.setUserId(form.getUserId());
entityManager.merge(user);

Вопрос:

Так что, если я правильно понял оптимистическую блокировку с помощью Hibernate, если я открою 2 вкладки в браузере для редактирования того же пользователя, затем обновимвойдите на первой вкладке и , затем войдите на второй вкладке, у меня должен быть OptimisticLockException не так ли?

На самом деле, это не так в моем приложении... Я проверил, form.getVersion() возвращает одинаковое значение в обоих случаях, даже если во втором обновлении user.version было обновлено при первом редактировании.

Я что-то упустил?

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * EntityManager * * * * * * * *1032* произведено @RequestScoped (поэтому я пытаюсь объединить две разные EntityManager s ...).

Я пытался сделать entityManager.lock(user, LockModeType.OPTIMISTIC_FORCE_INCREMENT)до entityManager.merge(...) (, как здесь сказано ), но это не помогло.

Я использую Seam 3 с JBoss 7.0.2.Final (который использует Hibernate 4).

Ответы [ 3 ]

7 голосов
/ 28 июня 2013

Я только что провел дополнительное исследование по этому вопросу.

запрещено изменять поле версии в соответствии со спецификацией JPA:

JPA 2.0 Окончательная спецификация, раздел 3.4.2:

Сущность может получить доступ к состоянию своего поля или свойства версии или экспортировать метод для использования приложением для доступа к версии, но не должен изменять значение версии . За исключением отмеченного в разделе 4.10, разрешено только поставщику постоянства устанавливать или обновлять значение атрибута версии в объекте.

Примечание. Раздел 4.10 относится к пакетным обновлениям, которые игнорируют атрибут версии.

6 голосов
/ 15 февраля 2012

На самом деле я нашел способ сделать это ... но я думаю, что он не очень эффективен (потому что есть еще 1 запрос SELECT).

User user = entityManager.find(User.class, userId)
user.setLogin(form.getLogin());
user.setVersion(form.getVersion());
user.setUserId(form.getUserId());

entityManager.detach(user);
entityManager.merge(user);

С entityManager.detach(user), теперь hibernate использует мое установленное значение version вместо своего собственного скопированного куда-то значения ...

1 голос
/ 06 ноября 2018

Найден другой способ запуска оптимистической блокировки вручную.Мы можем сравнить кэшированную версию Hibernate с версией в сущности.Я использую весенние данные JPA, и добавил FF.в хранилище сохраните реализацию:

EntityEntry entityEntry = entityManager
  .unwrap(SessionImplementor.class)
  .getPersistenceContext()
  .getEntry(entity);

//checked if a cached entry is present
if (entityEntry != null) {

  //Compare cached version with the one in the entity
  if (!Objects.equals(entityEntry.getVersion(), classMetadata.getVersion(entity))) {
    throw new ObjectOptimisticLockingFailureException();
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...