Здесь были некоторые дискуссии о сущностях 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()возвращаемое значение изменится, если вы измените одно из значений этого поля - что имеет смысл, если учесть что этот экземпляр объекта больше не "равен" значению, которое представлял старый экземпляр.
