Здесь были некоторые дискуссии о сущностях JPA и о том, какую hashCode()
/ equals()
реализацию следует использовать для классов сущностей JPA. Большинство (если не все) из них зависят от Hibernate, но я бы хотел обсудить их JPA-реализацию-нейтрально (кстати, я использую EclipseLink).
Все возможные реализации имеют свои преимущества и недостатки в отношении:
hashCode()
/equals()
соответствие контракта (неизменность) дляList
/Set
операций- Могут ли быть обнаружены идентичные объекты (например, из разных сеансов, динамические прокси из лениво загруженных структур данных)
- Правильно ли ведут себя сущности в отдельном (или непостоянном) состоянии
Насколько я вижу, есть три варианта :
- Не переопределяйте их; полагаться
Object.equals()
иObject.hashCode()
hashCode()
/equals()
работа- не может идентифицировать идентичные объекты, проблемы с динамическими прокси
- нет проблем с отдельными объектами
- Переопределите их, основываясь на первичном ключе
hashCode()
/equals()
сломаны- правильная идентификация (для всех управляемых объектов)
- проблемы с отдельными объектами
- Переопределите их, основываясь на Business-Id (поля не первичного ключа; как насчет внешних ключей?)
hashCode()
/equals()
сломаны- правильная идентификация (для всех управляемых объектов)
- нет проблем с отдельными объектами
Мои вопросы:
- Я пропустил опцию и / или за / за точку?
- Какой вариант вы выбрали и почему?
ОБНОВЛЕНИЕ 1:
К « hashCode()
/ equals()
сломаны», я имею в виду , что последовательные hashCode()
вызовы может возвращать различные значения, что (при правильной реализации) не нарушаюсь в смысле Object
документации API, но вызывает проблемы при попытке получить измененные сущности из Map
, Set
или других основанный на хэше Collection
. Следовательно, реализации JPA (по крайней мере, EclipseLink) в некоторых случаях не будут работать правильно.
ОБНОВЛЕНИЕ 2:
Спасибо за ваши ответы - большинство из них имеют замечательное качество.
К сожалению, я все еще не уверен, какой подход будет лучшим для реального приложения или как определить лучший подход для моего приложения. Поэтому я оставлю вопрос открытым и надеюсь на дальнейшие обсуждения и / или мнения.
hashcode()
одного и того же экземпляра объекта должен возвращать одно и то же значение, если только не equals()
изменятся поля, используемые в реализации. Другими словами, если у вас есть три поля в вашем классе, и ваш equals()
метод использует только два из них для определения равенства экземпляров, то вы можете ожидать, что hashcode()
возвращаемое значение изменится, если вы измените одно из значений этого поля - что имеет смысл, если учесть что этот экземпляр объекта больше не "равен" значению, которое представлял старый экземпляр.