Доменные объекты как идентификаторы создают некоторые сложные / тонкие проблемы:
Сериализация / десериализации
Если вы храните объекты в качестве ключей, это очень усложнит сериализацию графа объектов. Вы получите stackoverflowошибки при выполнении наивной сериализации в JSON или XML из-за рекурсии. Затем вам нужно будет написать собственный сериализатор, который преобразует фактические объекты, чтобы использовать их идентификаторы вместо сериализации экземпляра объекта и создания рекурсии.
Передавайте объекты для безопасности типов, но сохраняйте только идентификаторы, тогда у вас может быть метод доступа, который лениво загружает связанный объект при его вызове. Кэширование второго уровня позаботится о последующих вызовах.
Тонкие эталонные утечки:
Если вы используете доменные объекты в таких же конструкторах, как и у вас, вы создадите циклические ссылки, которые будут очень трудными для восстановления памяти для объектов, которые не используются активно.
Идеальная ситуация:
Непрозрачные идентификаторы против int / long:
idДолжна быть полностью непрозрачным идентификатором , который не несет никакой информации о том, что она идентифицирует. Но он должен предложить некоторую проверку того, что он является действительным идентификатором в своей системе.
Сырые типы ломают это:
int, longИ Stringнаиболее часто используемые типы сырья для идентификаторов в системе RDBMS. Практические причины, которые датируются десятилетиями, имеют долгую историю, и все они являются компромиссами, которые либо вписываются в сбережения, spaceлибо в сбережения, timeлибо в оба варианта.
Последовательные идентификаторы являются худшими нарушителями:
Когда вы используете последовательный идентификатор, вы по умолчанию упаковываете временную семантическую информацию в идентификатор. Что не плохо, пока не используется. Когда люди начинают писать бизнес-логику, которая сортирует или фильтрует семантическое качество идентификатора, тогда они создают боль для будущих сопровождающих.
String поля являются проблематичными, потому что наивные дизайнеры будут упаковывать информацию в содержимое, обычно также во временную семантику.
Это также делает невозможным создание распределенной системы данных, поскольку 12437379123она не является уникальной в глобальном масштабе. Вероятность того, что другой узел в распределенной системе создаст запись с таким же номером, в значительной степени гарантируется, когда вы получаете достаточно данных в системе.
Затем вокруг него начинают работать хаки, и все это превращается в кучу дымящегося беспорядка.
Игнорирование огромных распределенных систем ( кластеров ) становится полным кошмаром, когда вы начинаете пытаться обмениваться данными с другими системами. Особенно, когда другая система не находится под вашим контролем.
Вы сталкиваетесь с точно такой же проблемой, как сделать свой идентификатор глобально уникальным.
UUID был создан и стандартизирован по причине:
UUIDможет страдать от всех проблем, перечисленных выше, в зависимости от того, что Versionвы используете.
Version 1использует MAC-адрес и время для создания уникального идентификатора. Это плохо, потому что несет семантическую информацию о месте и времени. Это само по себе не проблема, это когда наивные разработчики начинают полагаться на эту информацию для бизнес-логики. Это также приводит к утечке информации, которая может быть использована при любых попытках вторжения.
Version 2использует пользователей UIDили GIDи domian UIDили GUIвместо этого время Version 1так же плохо, как Version 1для утечки данных и риска этой информации для использования в бизнес-логике.
Version 3аналогично, но заменяет MAC-адрес и время MD5хэшем некоторого массива byte[]из чего-то, что определенно имеет семантическое значение. Существует нет утечки данных, чтобы беспокоиться, byte[]не может быть восстановлено из UUID. Это дает вам хороший способ детерминированного создания UUIDэкземпляров формы и какого-либо внешнего ключа .
Version 4 основывается только на случайных числах, что является хорошим решением, оно не несет в себе никакой семантической информации, но оно не детерминировано воссоздано.
Version 5так же, как, Version 4но использует sha1вместо md5.
Ключи домена и ключи данных транзакций
Я предпочитаю идентификаторы объекта домена, использовать Version 5или, Version 3если Version 5по каким-либо техническим причинам, запрещено использовать .
Version 3 отлично подходит для данных транзакций, которые могут быть распределены по многим машинам.
Если вы не ограничены пространством, используйте UUID:
Они гарантированно уникальны, выгружая данные из одной базы данных и загружая их в другую, вам никогда не приходилось беспокоиться о дублирующих идентификаторах, которые фактически ссылаются на разные данные домена.
Version 3,4,5 полностью непрозрачны, и именно так они и должны быть.
Вы можете иметь один столбец в качестве первичного ключа с, UUIDа затем вы можете иметь составные уникальные индексы для того, что было бы естественным составным первичным ключом.
Хранения не должно быть CHAR(36)либо. Вы можете хранить UUIDв собственном поле байтов / битов / чисел для данной базы данных, пока она еще индексируется.
наследие
Если у вас есть необработанные типы, и вы не можете их изменить, вы все равно можете абстрагировать их в своем коде.
Использование Version 3/5of of of UUIDвы можете передать Class.getName()+ String.valueOf(int)как a byte[]и иметь непрозрачный ссылочный ключ, который может быть восстановлен и детерминирован.