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

Я проходил секцию генерации Id справочного руководства Hibernate и "java persistence with Hibernate"

В Hibernate и JPA имеется несколько вариантов.

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

Я также ищу опрокидывающие пункты.

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

Я хочу получить образование по поводу компромиссов.

Есть ли какая-либо литература?

Ответ 1

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 генерирует идентификаторы, которые уникальны только для конкретной базы данных.

seqhilo

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

UUID

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

справ

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

родной

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

присвоен

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

выберите

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

иностранный

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

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

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

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

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

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

Ответ 2

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

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

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

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

  • IDENTITY
  • ПОСЛЕДОВАТЕЛЬНОСТЬ
  • TABLE

ИДЕНТИФИКАЦИЯ - только хороший выбор, если вы не можете использовать SEQUENCE (например, MySQL), потому что отключает пакетные обновления JDBC.

SEQUENCE является предпочтительным вариантом, особенно когда используется оптимизатор идентификатора, например объединенный или объединенный-lo.

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

Ответ 3


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

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

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

Ответ 4

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