Как выбрать стратегию генерации идентификатора при использовании JPA и Hibernate

102

Я проходил через раздел создания идентификаторов справочного руководства Hibernate и «Сохранение Java с Hibernate»

Есть довольно много вариантов, доступных с объединением Hibernate и JPA.

Я искал дополнительную документацию о том, как выбрать конкретную стратегию генерации идентификаторов.

Я также ищу переломные моменты.

Например, ожидается, что стратегия hilo снизит конкуренцию. Я предполагаю, что с этим выбором должен быть компромисс.

Я хочу узнать о компромиссах.

Есть ли литература?

Влад Михалча
источник

Ответы:

92

В API Doc это очень четко сказано.

Все генераторы реализуют интерфейс org.hibernate.id.IdentifierGenerator. Это очень простой интерфейс. Некоторые приложения могут предоставлять свои собственные специализированные реализации, однако Hibernate предоставляет ряд встроенных реализаций. Имена ярлыков для встроенных генераторов следующие:

приращение

генерирует идентификаторы типа long, short или int, которые уникальны только тогда, когда никакой другой процесс не вставляет данные в ту же таблицу. Не используйте в кластере.

идентичность

поддерживает столбцы идентичности в DB2, MySQL, MS SQL Server, Sybase и HypersonicSQL. Возвращаемый идентификатор имеет тип long, short или int.

последовательность

использует последовательность в DB2, PostgreSQL, Oracle, SAP DB, McKoi или генератор в Interbase. Возвращаемый идентификатор имеет тип long, short или int.

хило

использует алгоритм hi / lo для эффективной генерации идентификаторов типа long, short или int, учитывая таблицу и столбец (по умолчанию hibernate_unique_key и next_hi соответственно) в качестве источника значений hi. Алгоритм hi / lo генерирует идентификаторы, уникальные только для конкретной базы данных.

секхило

использует алгоритм hi / lo для эффективной генерации идентификаторов типа long, short или int с учетом именованной последовательности базы данных.

uuid

использует 128-битный алгоритм UUID для генерации идентификаторов типа string, уникальных в сети (используется IP-адрес). UUID кодируется как строка длиной 32 шестнадцатеричных цифры.

гид

использует строку GUID, сгенерированную базой данных, в MS SQL Server и MySQL.

родной

выбирает идентичность, последовательность или хило в зависимости от возможностей базовой базы данных.

назначен

позволяет приложению присвоить объекту идентификатор перед вызовом save (). Это стратегия по умолчанию, если элемент не указан.

Выбрать

извлекает первичный ключ, назначенный триггером базы данных, путем выбора строки по некоторому уникальному ключу и получения значения первичного ключа.

иностранный

использует идентификатор другого связанного объекта. Обычно он используется вместе с ассоциацией первичного ключа.

идентичность последовательности

специализированная стратегия генерации последовательности, которая использует последовательность базы данных для генерации фактического значения, но объединяет ее с JDBC3 getGeneratedKeys для возврата сгенерированного значения идентификатора как части выполнения инструкции вставки. Эта стратегия поддерживается только драйверами Oracle 10g, предназначенными для JDK 1.4. Комментарии к этим операторам вставки отключены из-за ошибки в драйверах Oracle.

Если вы создаете простое приложение с небольшим количеством одновременных пользователей, вы можете использовать инкремент, идентификацию, hilo и т. Д. Их легко настроить и не нужно много кодировать внутри базы данных.

Вы должны выбрать последовательность или руководство в зависимости от вашей базы данных. Это безопасно и лучше, потому что idгенерация будет происходить внутри базы данных.

Обновление: недавно у нас возникла проблема с идентификатором, когда примитивный тип (int) был исправлен с использованием вместо этого типа warapper (Integer).

МануПК
источник
Большое спасибо за Ваш ответ. Я уже просмотрел документы. Однако я ищу, почему люди будут использовать что-то вроде hilo и seqhilo. Когда мы сделаем этот выбор. Каковы варианты использования select.
Когда есть что-то настолько простое, как последовательность или руководство, что может потребовать от разработчика выбора других путей.
1
Я обновил свой ответ. На самом деле инкремент, идентичность, хило и т. Д. Проще. но они не подходят для корпоративных приложений. Сохранить все варианты - не проблема, но убедитесь, что вы выбрали наиболее подходящий для вас!
ManuPK 08
Да. Пока у меня не было привилегии проголосовать за или принять.
Я собираюсь погрузиться в подробности, если у вас будет время, дайте мне знать.
45

По сути, у вас есть два основных варианта:

  • Вы можете сгенерировать идентификатор самостоятельно, и в этом случае вы можете использовать назначенный идентификатор .
  • Вы можете использовать @GeneratedValueаннотацию, и Hibernate назначит вам идентификатор.

Для сгенерированных идентификаторов у вас есть два варианта:

Для числовых идентификаторов у вас есть три варианта :

  • ИДЕНТИЧНОСТЬ
  • ПОСЛЕДОВАТЕЛЬНОСТЬ
  • СТОЛ

IDENTITY - хороший выбор только тогда, когда вы не можете использовать SEQUENCE (например, MySQL), потому что он отключает пакетные обновления JDBC .

ПОСЛЕДОВАТЕЛЬНОСТЬ - предпочтительный вариант, особенно при использовании с оптимизатором идентификаторов, например pooled или pooled-lo .

ТАБЛИЦЫ следует избегать любой ценой, поскольку она использует отдельную транзакцию для получения идентификатора и блокировок на уровне строк, которые плохо масштабируются.

Влад Михалча
источник
20


Некоторое время назад я написал подробную статью о генераторах ключей Hibernate: http://blog.eyallupu.com/2011/01/hibernatejpa-identity-generators.html

Выбор правильного генератора - сложная задача, но важно попытаться исправить это как можно скорее - поздняя миграция может стать кошмаром.

Немного не по теме, но хороший шанс поднять вопрос, который обычно упускается из виду, а именно об обмене ключами между приложениями (через API). Лично я всегда предпочитаю суррогатные ключи, и если мне нужно передать свои объекты другим системам, я не раскрываю свой ключ (даже если он суррогатный) - я использую дополнительный «внешний ключ». Как консультант, я не раз видел «отличные» системные интеграции с использованием объектных ключей (подход «это есть, давайте просто воспользуемся этим») только для того, чтобы через год или два обнаружить, что у одной стороны есть проблемы с диапазоном ключей или чем-то вроде этого. требующие глубокой миграции в системе с открытием ее внутренних ключей. Раскрытие ключа означает, что нельзя подвергать фундаментальный аспект вашего кода внешним ограничениям.

Эял Лупу
источник
2

Я считаю эту лекцию очень ценной https://vimeo.com/190275665 , в пункте 3 она обобщает эти генераторы, а также дает некоторый анализ производительности и рекомендации по использованию каждого из них.

Аделин
источник
6
Это видео выглядит очень знакомо.
Влад Михалча