Страницы

Поиск по вопросам

воскресенье, 29 декабря 2019 г.

Equals(), hashCode() + ORM

#java


Нужно ли в классах ентити всегда переопределять методы equals() и hashCode() ?
И что значит не используйте ссылки на поля в методах equals() и hashCode() если классы
задействованны в ORM ?
    


Ответы

Ответ 1



Перегружать equals и hashCode в Entity-классах, используемых в ORM нужно по тем же причинам, по которым это нужно в других случаях: корректное сравнение объектов, полученных из разных источников (для ORM - в разных сессиях) корректное хранение объектов в Hash* и *Set коллекциях Нежелательность использования ссылок на поля в equals и hashCode в классах, используемых ORM, вызвано тем, что большинство ORM возвращают не непосредственно объекты вашего класса, а прокси. Прокси наследуются от ваших классов и перегружают геттеры. Во многих ORM по умолчанию стратегия получения объектов - lazy (ленивая). Это значит, что в момент, когда вы получаете объект, вы получаете пустую прокси. И только когда вы получаете значения полей через геттеры, выполняется запрос к базе, извлекающий значения полей и заполняющий ими объект. Если вы в equals или hashCode будете использовать ссылки на поля, вы можете попасть в ситуацию, когда в сравнении или вычислении хеша участвует ещё не заполненный объект. Поэтому вместо прямого доступа к полям следует использовать геттеры. Естественно, вышесказанное относится к ORM, умеющим загружать объекты "лениво", например, к Hibernate. А вот ORM вроде MyBatis грузят объект целиком, поэтому там использование ссылок на поля в методах объекта вполне уместно.

Ответ 2



ORM классы лучше (вот прям очень сильно лучше, если только вам совсем выбора не оставили) не трогать, так как они предназначенны для отображения структуры БД и только, да и нормальные люди их генерируют, если есть возможность, и с каждой генерацией ваши методы вылетать будут. Hash - это "техническая" эквивалентность, как от прокси объекта считать? И самое главное - зачем? Настоятельно рекомендую ORM и все с ними связанное (репозитории и т.п.) не пускать дальше вашего ДБ слоя/пакета/модуля, а заполнять свои pojo классы (или любые другие модельные классы) на месте, пока транзакция еще бежит и тогда весь бред с прокси и т.п. сразу решается, так сказать. И остальная часть приложения никак не зависит от ORM фреймворка, захотели и заменили провайдера своей модели на xml или messages фреймворк и т.д. и т.п. А так - да, их имплементация - это часть контракта Жабы, только надо понимать, что hashCode логика сломана! И лучше объекты эти делать имутабельными, т.к. hash коллекции и т.п. не обновят карзину объекта, если его поля поменяются. При сложной иерархии классов смешных эффектов еще больше.

Комментариев нет:

Отправить комментарий