Объектное равенство в контексте в спящем режиме / веб-приложение

Как Вы обрабатываете объектное равенство для объектов Java, управляемых, в спящем режиме? В 'в спящем режиме в действии' книга, они говорят, что нужно одобрить бизнес-ключи по суррогатным ключам.
Большую часть времени у меня нет бизнес-ключа. Думайте об адресах, отображенных на человеке. Адреса сохранены в Наборе и отображены в Калитке RefreshingView (со стратегией ReuseIfEquals).

Я мог или использовать суррогатный идентификатор или использовать все поля в равнянии () и хэш-код () функции.
Проблема состоит в том, что те поля изменяют во время пожизненной Оби объект. Или потому что пользователь вошел, некоторые данные или идентификатор изменяются из-за слияния JPA () называемый в OSIV (Открытое заседание в поле зрения) фильтр.

Мое понимание равняния () и хэш-код () контракт - то, что они не должны изменяться в течение времени жизни объекта.

Что я попробовал до сих пор:

  • равняется () на основе хэш-кода (), который использует идентификатор базы данных (или super.hashCode (), если идентификатор является пустым). Проблема: новые адреса запускаются с пустого идентификатора, но получают идентификатор при присоединении к человеку и этот человек объединяется () (повторно прикрепленный) в osiv-фильтре.
  • ленивый вычисляют хэш-код, когда хэш-код () сначала называют, и сделайте тот хэш-код @Transitional. Не работает, поскольку слияние () возвращает новый объект, и хэш-код не становится скопированным.

То, в чем я нуждался бы, является идентификатором, который присвоен во время создания объекта, я думаю. Каковы были бы мои опции здесь? Я не хочу представлять некоторое дополнительное персистентное свойство. Существует ли способ явно сказать JPA присваивать идентификатор объекту?

С уважением

13
задан bert 27 April 2010 в 08:56
поделиться

5 ответов

Использование id объекта не является хорошей идеей, потому что временные объекты еще не имеют идентификатора (и вы все равно хотите, чтобы временные объекты были потенциально равными к настойчивому).

Использование всех свойств (кроме идентификатора базы данных) также не является хорошей идеей, потому что все свойства просто не являются частью идентичности.

Таким образом, предпочтительный (и правильный) способ реализовать равенство - использовать бизнес-ключ , как объясняется в Сохранение Java с Hibernate :

Реализация равенства с бизнесом key

Чтобы найти решение, которое мы рекомендуем, вам необходимо понимать понятие бизнес-ключа. Бизнес-ключ - это свойство или некоторая комбинация свойств, которые уникальны для каждого экземпляра с одним и тем же идентификатором базы данных. По сути, это естественный ключ, который вы бы использовали, если бы вместо него не использовали суррогатный первичный ключ. В отличие от естественного первичного ключа, это не является абсолютным требованием, чтобы бизнес-ключ никогда не изменения - пока оно меняется редко, этого достаточно.

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

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

Для класса «Пользователь» имя пользователя является отличным кандидатом для бизнес-ключа. Он никогда не равен нулю, он уникален с учетом ограничения базы данных и меняется редко, если вообще когда-либо:

  public class User {
 ... 
public boolean equals (Object other ) {
if (this == other) return true; 
if (! (Other instanceof User)) return false; 
final User that = (User) other; {{ 1}} return this.username.equals (that.getUsername ()); 
 
public int hashCode () {
return username.hashCode (); {{1} }} 
} 
 

Возможно, я что-то упустил, но для Адреса бизнес-ключ обычно состоит из номера улицы, улицы, города, почтового индекса, страны. Я не вижу в этом проблем.

На всякий случай, Equals And HashCode - еще одно интересное чтение.

15
ответ дан 2 December 2019 в 00:17
поделиться

Я использую для этого так: equal и hashcode используют ключ, когда он был установлен, в противном случае equals использует базовая реализация (она же ==). Он также должен работать, если hashcode () возвращает super.hashcode () вместо 0.

@Override
public int hashCode() {
    if (code == null) {
        return 0;
    } else {
        return code.hashCode();
    }
}

@Override
public boolean equals(Object obj) {
    if (obj instanceof PersistentObject && Hibernate.getClass(obj).equals(Hibernate.getClass(this))) {
        PersistentObject po = (PersistentObject) obj;

        if (code == null) {
            return po.code == null && this == po;
        } else {
            return code.equals(po.getCode());
        }
    } else {
        return super.equals(obj);
    }
}
0
ответ дан 2 December 2019 в 00:17
поделиться

Вопрос в том, как часто у вас может быть несколько несохраненных объектов, которые могут быть дубликатами, которые необходимо добавить в набор или карту? Для меня ответ практически никогда не бывает, поэтому я использую суррогатные ключи и super.equals / hashcode для несохраненных объектов.

Бизнес-ключи в некоторых случаях имеют смысл, но они могут вызвать проблемы. Например, что, если два человека живут по одному адресу - если вы хотите, чтобы это была одна запись в базе данных, вы должны управлять ею как многие-ко-многим и потерять возможность каскадного удаления, чтобы, когда последняя человек, живущий там, удален, вам нужно проделать дополнительную работу, чтобы избавиться от адреса. Но если вы храните одни и те же адреса для каждого человека, тогда ваш бизнес-ключ должен включать объект person, что может означать попадание в базу данных внутри ваших методов equals / hashcode.

0
ответ дан 2 December 2019 в 00:17
поделиться

Может быть, это сделает свойство transient ? Таким образом, вам не придется беспокоиться о постоянстве. Как это:

@Transient
private Integer otherId;
0
ответ дан 2 December 2019 в 00:17
поделиться

Спасибо за ваш вклад. Я решил использовать суррогатные ключи и предоставить их прямо во время создания объекта. Таким образом, я избегаю всего этого «редко» меняющегося материала и имею что-то твердое, на чем можно основывать свою идентичность. Первые тесты выглядят неплохо.

спасибо всем за ваше время. К сожалению, я могу принять только один ответ в качестве решения. Я возьму Паскаль, так как он дал мне хорошее чтение;)

наслаждайтесь

0
ответ дан 2 December 2019 в 00:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: