Hibernate: обновлять поле в сущности, только если определенное поле пусто - PullRequest
0 голосов
/ 27 апреля 2011

У меня есть следующее:

public class Member {

    @Id
    @Column
    private String id;

    @Column
    private String location;

    // setters/getters
}

Я должен реализовать следующие бизнес-правила:

Установить местоположение:

  1. Получить член из БД на основеid.
  2. Если местоположение равно нулю, присвойте ему значение и сохраните, в противном случае ничего не делайте.

public void setLocation(String id, String location){
    Member m = memberDao.find(id); // assume m is not null
    if(null == m.getLocation()){
         m.setLocation(location);
         memeberDao.saveOrUpdate(m);
    }
    else
        throw new MemberAlreadyHasALocationException();
}

Удалить местоположение:

  1. Получитьчлен из БД на основе идентификатора.
  2. Если для местоположения задано ненулевое значение, а текущее значение равно значению параметра, установите для местоположения нулевое значение и обновите, в противном случае ничего не делайте

public void removeLocation(String id, String location){
    Member m = memberDao.find(id);
    if(m.getLocation() != null && m.getLocation.equalsIgnoreCase(location)){
         m.setLocation(null);
         memeberDao.saveOrUpdate(m);
    }
}

Мне поручено решать проблемы параллелизма, но я не уверен, как это сделать в спящем режиме.Более конкретно, как я могу обрабатывать одновременные вызовы setLocation для одного и того же идентификатора, учитывая, что у объекта с этим идентификатором в настоящее время нет местоположения.

По сути, первое обновление должно выиграть, а второе - не получится.

Достаточно ли добавить версию в класс Member


@Version
@Column(name="version")
private Long version;

Однако, скажем, что есть поле пола, я бы хотел обновить поле пола, не заботясь, еслиместоположение обновляется другой транзакцией.

Спасибо.

1 Ответ

0 голосов
/ 28 апреля 2011

В основном первое обновление должно выиграть и второй должен потерпеть неудачу.

Достаточно ли добавить версию в Член класса

Да, это так. Скажем, мы с вами читаем сущность из базы данных с версией = х. Я делаю некоторые изменения в property1 объекта и фиксирую в базе данных. Теперь объект в базе данных имеет версию = x + 1. Теперь вы изменяете property2 вашей версии сущности (property1 по-прежнему содержит старое значение). Когда вы обновляете измененную сущность в базе данных, сделанные мной изменения в property1 будут потеряны, так как вы перезапишете ее старым значением. Но этого не произойдет, поскольку Hibernate будет проверять любые изменения, которые могли произойти между моментом чтения объекта и его обновления. Когда вы переходите на обновление сущности, Hibernate видит, что версия сущности в базе данных отличается от версии предоставленной вами сущности. Это означает, что кто-то еще сделал некоторые изменения в объекте, то есть предоставленный вами объект устарел, и, следовательно, генерируется исключение StaleStateException.

Однако, скажите, что есть пол поле, я хотел бы иметь возможность обновить поле пола, не заботясь если местоположение обновляется другая транзакция.

Это невозможно при использовании hibernate (это должно быть ясно из приведенного выше примера). Если бы это было поддержано, то изменения, внесенные в местоположение, будут потеряны, когда будет зафиксировано обновление, сделанное для пола, содержащее более старое значение местоположения. Некоторая степень допуска может быть достигнута с помощью некоторой логической и явной проверки версии и обновления измененных полей перед обновлением сущности, но проблема все еще существует, вы никогда не можете знать, в какой момент будут внесены изменения в объект. По моему мнению, такая реализация будет излишним с недостаточной пользой.

...