Да, важно, чтобы ваш элемент использовался как ключ в словаре, или HashSet
и т. д. - поскольку он используется (при отсутствии пользовательского IEqualityComparer
) для группировки элементов в ведра. Если хэш-код для двух элементов не соответствует, они могут never считаться равными (Equals
просто никогда не будет вызываться).
Метод GetHashCode()
должен отражать логика Equals
; следующие правила:
Equals(...) == true
), то они должны возвращать одно и то же значение для GetHashCode()
GetHashCode()
равен, для них необходимо не , чтобы они были одинаковыми; это столкновение, и Equals
будет вызываться, чтобы убедиться, что это реальное равенство. В этом случае это выглядит так: «return FooId;
» является подходящим GetHashCode()
. Если вы тестируете несколько свойств, обычно их объединяют с использованием кода, как показано ниже, для уменьшения диагональных столкновений (т. Е. Для new Foo(3,5)
имеет другой хеш-код для new Foo(5,3)
):
int hash = 13;
hash = (hash * 7) + field1.GetHashCode();
hash = (hash * 7) + field2.GetHashCode();
...
return hash;
Ох - для удобства вы можете также рассмотреть возможность предоставления операторов ==
и !=
при переопределении Equals
и GetHashCode
.
Демонстрация того, что происходит, когда вы ошибаетесь здесь .
При использовании @Id
аннотация с полями непосредственно поддерживаемых типов не является единственным способом определить идентификационные данные объекта (см. @IdClass
приблизительно с @Id
аннотации или @EmbeddedId
с @Embedded
), спецификация JPA требует первичного ключа для каждого объекта.
Тем не менее Вам не нужны объекты для использования JPA с представлениями базы данных. Как отображающийся на представление не отличается от отображения до таблицы с точки зрения SQL, Вы могли все еще использовать собственные запросы (createNativeQuery
на EntityManager
) для получения скалярных величин вместо этого.
Я сам разбирался в этом и нашел хак, который, я не уверен, работает на 100%, но выглядит многообещающим.
В моем случае у меня есть столбец FK в представлении, который может эффективно функционировать как PK - любой конкретный экземпляр этого постороннего объекта может появиться в представлении только один раз. Я определил два объекта вне этого поля: один обозначен как ID и представляет необработанное значение поля, а другой предназначен только для чтения и представляет объект, на который делается ссылка.
@Id
@Column(name = "foreignid", unique = true, nullable = false)
public Long getForeignId() {
...
@OneToOne
@JoinColumn(name = "foreignid", insertable=false, updatable=false)
public ForeignObject getForeignObject() {
...
Как я уже сказал, я не уверен на 100% по этому вопросу (и я просто удалю этот ответ, если он окажется, что он не работает), но мой код прошел через определенную точку сбоя.
Не знаю, применимо ли это к вашей конкретной ситуации. И есть отличный шанс, что через 11 месяцев вам будет все равно. :-) Какого черта, значок "Некромант" не заработал сам себя ....