2014-11-21 3 views
3

Существует огромное значение, которое должно быть получено путем присвоения идентификатора объекту до его сохранения в базе данных, но сразу же в конструкторе: реализация equals/hashcode становится тривиальной, and it saves many headaches.генерация последовательности идентификаторов jpa

Я видел проблемы, когда предприятие равенство основано на ==: проксите-сервер получает в сессии, и когда он получает разворачивали как реальный объект, вы получите equals(), который возвращает false.

И когда вы переопределить equals и hashcode использовать сгенерированный идентификатор, потому что один генерируется только на persist(), все не сохранились объекты имеют идентификатор null и, следовательно, все равны друг другу.

Из того, что я читал, когда вы используете традиционную технологию генерации идентификатора (например, автоинкремент), идентификатор генерируется, когда диспетчер объектов очищается. Когда вы используете решение на основе последовательностей, оно генерируется в режиме persist-time.

Эта статья и мое нынешнее понимание говорят, что самым простым решением является назначение идентификатора во время создания, а не для сохранения или очистки. И с последовательностями, которые кажутся доступными, но JPA решила против него. С получением идентификаторов, являющихся чем-то дешевым с последовательностями (как вы можете выполнить предварительную выборку), почему JPA не предоставила хотя бы вариант получения идентификатора на основе последовательности уже при создании объекта? Существует риск потерять некоторые идентификаторы, если сущность на самом деле не сохраняется в конце, но я думаю, что это не большая проблема.

Запрет на то, что единственными «без компромиссов» в отношении простоты и понятности решения являются UUID, у которых есть свои проблемы.

Я что-то упустил? Может быть, где-то есть какой-то генератор идентичности JPA или какая-то библиотека, которая будет основана на последовательности и позволит дать идентификатор во время строительства?

ответ

2

Использование assigned identifier - лучший подход с точки зрения письма. Он также согласован во всех entity state transitions, и вы даже можете выполнять пакетные вставки на уровне JDBC.

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

Для идентификатора, назначенного для базы данных, необходимо учитывать, насколько по-прежнему влияет промывка. Hibernate пытается отложить Persistence Context flushing up until the last possible moment. Эта стратегия традиционно известна как транзакционная запись.

Ссылка на запись больше связана с промывкой Hibernate, а не с любой логической или физической транзакцией. Во время транзакции флеш может возникать несколько раз.

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

IDENTITY requires flushing, в то время как последовательность не является транзакционной, поэтому она не требует флеша. IDENTITY отключает пакетную загрузку JDBC и не поддерживает предварительное выделение.

JPA не может назначить идентификатор во время построения Entity, потому что новый экземпляр может сохраняться только через вызов EntityManager.persist(). JPA требует явных «переходов состояний объекта».

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

+0

Я все еще не понимаю. С числовым типом, поддерживаемым последовательностью, если вы предварительно выбираете значения последовательности, вы все равно получаете пакетные записи, вы все равно получаете хорошую индексацию, вам не нужно промывать. В моем ограниченном понимании я не вижу необходимости привязывать постоянное и сущность к присвоению ему идентификатора, поэтому я не понимаю, почему не назначать ранее зарезервированный порядковый номер в качестве идентификатора во время построения? Особенно, если отходы не являются проблемой. –

+0

, так что я бы использовал предварительно выбранные значения последовательности вместо UUID, мне кажется, что я получаю плюсы UUID (генерация минус ID на клиенте) без проблем с производительностью и пространством, но я не нашел готового решения (генератор), что меня удивляет. –

+1

Я рекомендую вам начать использовать оптимизатор [pooled-lo optimizer] (http://vladmihalcea.com/2014/07/21/hibernate-hidden-gem-the-pooled-lo-optimizer/) вместе с генератором последовательности. Следуйте по этой ссылке, чтобы узнать, как вы можете это сделать. –

Смежные вопросы