Доменные объекты как идентификаторы создают некоторые сложные / тонкие проблемы:
Сериализация / десериализации
Если вы храните объекты в качестве ключей, это очень усложнит сериализацию графа объектов. Вы получите 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/5
of of of UUID
вы можете передать Class.getName()
+ String.valueOf(int)
как a byte[]
и иметь непрозрачный ссылочный ключ, который может быть восстановлен и детерминирован.