Поддерживает ли спецификация JPA оптимистическая блокировка проверки по версии, предоставленной клиентом - PullRequest
0 голосов
/ 19 мая 2018

Предположим, у меня есть сущность, определенная следующим образом:

@Entity
public class MyEntity {
    @Id
    @GeneratedValue
    private Integer id;

    @Column
    private String name;

    @Version
    int version;

    // Getters + setters
}

Предположим, у меня также есть служба (API REST или что-то подобное), которая позволяет пользователю получать информацию об этой сущности.Возвращает идентификатор, текущее имя и текущую версию.Существует также другая служба, которая позволяет пользователю обновлять имя объекта.Он принимает идентификатор, имя обновления и версию в качестве входных параметров.Таким образом, сущность может быть обновлена ​​путем создания нового объекта и использования слияния:

public MyEntity update(EntityManager em, int id, String name, int version) {
    MyEntity entity = new Entity();
    entity.setId(id);
    entity.setName(name);
    entity.setVersion(version);
    return em.merge(entity);
}

В качестве альтернативы его можно обновить, извлекая его из базы данных и обновляя только соответствующие поля:

public MyEntity update(EntityManager em, int id, String name, int version) {
    MyEntity entity = em.find(MyEntity.class, id);
    entity.setName(name);
    entity.setVersion(version);
    return entity;
}

Мое тестирование говорит мне, что в Hibernate 5.3 первый сценарий вызовет исключение OptimisticLockException (с сообщением Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)), если предоставленная версия не совпадает с тем, что находится в базе данных.Однако второй сценарий работает нормально, и имя обновляется независимо от предоставленной версии.

Я также пробовал это с DataNucleus 5.1.9, и ни один из сценариев не выдает исключение, а имя обновляется независимо от версии.поставляется в обоих случаях.

Так что я думаю, что либо есть ошибка в Hibernate, либо DataNucleus, один из них не соответствует спецификации JPA, либо в спецификации не указано, как это должно работать?

Я пытался найти окончательный ответ на этот вопрос, но не смог этого сделать.Может кто-нибудь подтвердить, как, согласно спецификации JPA, должна работать оптимистическая блокировка, когда дело доходит до обновления сущностей с номером версии, предоставляемым извне?

1 Ответ

0 голосов
/ 19 мая 2018

Э-э-э-э, внешняя установка поля @Version?Это, вероятно, приведет в большинстве случаев к конфликтам, так как это не должно быть установлено разработчиком.Он управляется исключительно поставщиком персистентности.Вам не понадобятся getter или setter для доступа к version.

Выдержка из спецификации JPA 2.0:

Поле или свойство Version используется поставщиком сохраняемости для выполнения оптимистической блокировки.К нему обращаются и / или устанавливают поставщик постоянства в ходе выполнения операций жизненного цикла на экземпляре объекта.Сущность автоматически включается для оптимистической блокировки, если у нее есть свойство или поле, сопоставленные с сопоставлением версии.Сущность может получить доступ к состоянию своего поля или свойства версии или экспортировать метод для использования приложением для доступа к версии, но не должна изменять значение версии [34].За исключением случаев, отмеченных в разделе 4.10, только поставщику постоянства разрешается устанавливать или обновлять значение атрибута версии в объекте.

Относительно процесса обновления: вы обычно получаете идентификатор вашего объектаи данные, которые вы хотите изменить из своего интерфейса отдыха.Вы передаете оба Service, в котором вы указываете своему EntityManager, что нужно выбрать объект с указанным идентификатором, обновлять данные об этом объекте и сообщаете EntityManager, чтобы он сразу же был сохранен.Эта процедура не высечена на камне, но примерно так она и делается в большинстве случаев.

Оба метода setID() и setVersion() для ваших энтитов, скорее всего, будут плохой практикой.

...