JAVAARCHIVEBOOKS Telegram 205
Hashcode для Hibernate сущностей

Год новый, а темы всё те же. В декабрьском адвенте разгорелась горячая дискуссия на тему hashcode. Встал такой вопрос:

Как определить hashcode для сущностей Hibernate? Что делать, если объект пока не сохранён в БД и у него нет id?

В этом вопросе часто упоминается статья Thorben Janssen Ultimate Guide to Implementing equals() and hashCode() with Hibernate

В самом конце там вывод: если для сущности id генерируется в БД, то hashcode должен возвращать константу.

Почему это не лучший вариант?

Контракт соблюдается, всё работает корректно. Но задача хэша — быстрая проверка схожести объектов. Мы теряем преимущество быстрого поиска, и хэшсет будет работать как список. Так будет и для новых объектов, и для уже сохранённых (у которых id есть).

Другие авторы рекомендуют считать хэш Hibernate сущностей на основе всех полей кроме id. В чём недостатки такого решения:

Если поля изменяемые, есть шанс потерять объект внутри HashSet
Цель хэша — быстрая проверка. Если считать хэш всех полей, с тем же успехом можно использовать списки и сравнение через equals

Что же делать?

1️⃣ Использовать для хэша любое неизменяемое поле

Даже если поле не уникальное, распределение хэшей будет лучше, чем у константы

2️⃣ Не использовать хэш-структуры для новых объектов

Новые объекты собирать в список:
List users = …
users.forEach(u -> session.save(u));

Тогда в хэшкоде можно спокойно использовать id и для уже сохранённых объектов хэшсет будет работать как надо:
Set users = …
if (!users.contains(…)) {…}

Итого:

🔸 Hashcode нужен только, когда структура используется в hash-based структурах. Если новые объекты не складываются в HashSet или HashMap, то проблемы вообще нет

🔸 Если вы хотите возвращать в хэшкод константу, рассмотрите вариант хранения сущностей в ArrayList или TreeSet

Ответ на вопрос перед постом: зависит от сценариев использования. Если новые объекты User собираются в коллекцию, я бы складывала в список, а hashcode реализовала как return id; Но ситуации бывают разные, решение не универсально.

И более глобальные выводы:

Хороших материалов по разработке мало. Но даже в хороших легко свернуть не туда. Статья Thorben Janssen в целом ок, но итог немного сбивает с толку. Сравните:

💁🏼‍♂️ "Если для сущности id генерируется в БД, hashcode должен возвращать константу"

💁🏼 "Если новые Hibernate сущности складываются в hash структуры, и у них нет final полей, то для соблюдения контракта можно использовать в hashcode константу"

Второй вариант корректнее, но первый проще и лучше запоминается.

Не попадайте в эту ловушку. Задача разработчика — разобраться в сценариях, оценить варианты и найти подходящий😌
🔥3👍1



tgoop.com/javaarchivebooks/205
Create:
Last Update:

Hashcode для Hibernate сущностей

Год новый, а темы всё те же. В декабрьском адвенте разгорелась горячая дискуссия на тему hashcode. Встал такой вопрос:

Как определить hashcode для сущностей Hibernate? Что делать, если объект пока не сохранён в БД и у него нет id?

В этом вопросе часто упоминается статья Thorben Janssen Ultimate Guide to Implementing equals() and hashCode() with Hibernate

В самом конце там вывод: если для сущности id генерируется в БД, то hashcode должен возвращать константу.

Почему это не лучший вариант?

Контракт соблюдается, всё работает корректно. Но задача хэша — быстрая проверка схожести объектов. Мы теряем преимущество быстрого поиска, и хэшсет будет работать как список. Так будет и для новых объектов, и для уже сохранённых (у которых id есть).

Другие авторы рекомендуют считать хэш Hibernate сущностей на основе всех полей кроме id. В чём недостатки такого решения:

Если поля изменяемые, есть шанс потерять объект внутри HashSet
Цель хэша — быстрая проверка. Если считать хэш всех полей, с тем же успехом можно использовать списки и сравнение через equals

Что же делать?

1️⃣ Использовать для хэша любое неизменяемое поле

Даже если поле не уникальное, распределение хэшей будет лучше, чем у константы

2️⃣ Не использовать хэш-структуры для новых объектов

Новые объекты собирать в список:

List users = …
users.forEach(u -> session.save(u));

Тогда в хэшкоде можно спокойно использовать id и для уже сохранённых объектов хэшсет будет работать как надо:
Set users = …
if (!users.contains(…)) {…}

Итого:

🔸 Hashcode нужен только, когда структура используется в hash-based структурах. Если новые объекты не складываются в HashSet или HashMap, то проблемы вообще нет

🔸 Если вы хотите возвращать в хэшкод константу, рассмотрите вариант хранения сущностей в ArrayList или TreeSet

Ответ на вопрос перед постом: зависит от сценариев использования. Если новые объекты User собираются в коллекцию, я бы складывала в список, а hashcode реализовала как return id; Но ситуации бывают разные, решение не универсально.

И более глобальные выводы:

Хороших материалов по разработке мало. Но даже в хороших легко свернуть не туда. Статья Thorben Janssen в целом ок, но итог немного сбивает с толку. Сравните:

💁🏼‍♂️ "Если для сущности id генерируется в БД, hashcode должен возвращать константу"

💁🏼 "Если новые Hibernate сущности складываются в hash структуры, и у них нет final полей, то для соблюдения контракта можно использовать в hashcode константу"

Второй вариант корректнее, но первый проще и лучше запоминается.

Не попадайте в эту ловушку. Задача разработчика — разобраться в сценариях, оценить варианты и найти подходящий😌

BY Уютное сообщество джавистов




Share with your friend now:
tgoop.com/javaarchivebooks/205

View MORE
Open in Telegram


Telegram News

Date: |

The imprisonment came as Telegram said it was "surprised" by claims that privacy commissioner Ada Chung Lai-ling is seeking to block the messaging app due to doxxing content targeting police and politicians. The Channel name and bio must be no more than 255 characters long A new window will come up. Enter your channel name and bio. (See the character limits above.) Click “Create.” Telegram channels fall into two types: Select “New Channel”
from us


Telegram Уютное сообщество джавистов
FROM American