Об'єкти домену як ідентифікатори створюють деякі складні / тонкі проблеми:
Серіалізація / десеріалізація
Якщо ви зберігаєте об’єкти як ключі, це зробить серіалізацію об'єктного графіка надзвичайно складним. Ви отримаєте stackoverflowпомилки, роблячи наївну серіалізацію в JSON або XML через рекурсію. Тоді вам доведеться написати спеціальний серіалізатор, який перетворює фактичні об'єкти для використання їх ідентифікаторів, а не серіалізації об’єктного об'єкта та створення рекурсії.
Передайте об'єкти для безпеки типу, але зберігайте лише ідентифікатори, тоді ви можете мати метод аксесуара, який ледачий завантажує відповідний об'єкт, коли він викликається. Кешування другого рівня забезпечить наступні дзвінки.
Тонкі довідкові витоки:
Якщо ви використовуєте об’єкти домену в таких конструкторах, ви створите кругові посилання, що буде дуже важко дозволити відновленню пам'яті для об'єктів, які активно не використовуються.
Ідеальна ситуація:
Непрозорі ідентифікатори проти int / long:
idПовинна бути повністю непрозорим ідентифікатором , який не несе ніякої інформації про те, що вона ідентифікує. Але він повинен запропонувати певну перевірку того, що він є дійсним ідентифікатором у своїй системі.
Сирі види порушують це:
int, longі Stringє найбільш часто використовуваними типами сировини для ідентифікаторів в системі RDBMS. Існує довга історія практичних причин, які датуються десятиліттями, і всі вони є компромісами, які або вкладаються в економію, spaceабо в економію, timeабо в обидва.
Послідовні ідентифікатори - найгірші правопорушники:
Коли ви використовуєте послідовний ідентифікатор, ви за замовчуванням запакуєте тимчасову семантичну інформацію в ідентифікатор. Що непогано, поки його не використовують. Коли люди починають писати ділову логіку, яка сортує або фільтрує семантичну якість ідентифікатора, тоді вони створюють світ болю для майбутніх утримувачів.
String поля є проблематичними, тому що наївні дизайнери запакуватимуть інформацію у зміст, як правило, також у часовій семантиці.
Це робить неможливим і створення розподіленої системи даних, оскільки 12437379123вона не є єдиною в усьому світі. Шанси, що інший вузол в розподіленій системі створить запис з однаковим числом, майже гарантовані, коли ви отримаєте достатньо даних у системі.
Потім хаки починають працювати навколо нього, і вся річ перетворюється на купу пареного безладу.
Ігнорування величезних розподілених систем ( кластерів ) стає повним кошмаром, коли ви починаєте обмінюватися даними також з іншими системами. Особливо, коли інша система не під вашим контролем.
У вас з'являється та сама проблема, як зробити свій ідентифікатор глобальним.
UUID створено та стандартизовано з причини:
UUIDможе страждати від усіх перерахованих вище проблем, залежно від того, якими Versionви користуєтесь.
Version 1використовує MAC-адресу та час для створення унікального ідентифікатора. Це погано, оскільки воно несе смислову інформацію про місце та час. Це само по собі не є проблемою, це коли наївні розробники починають покладатися на цю інформацію для ділової логіки. Це також просочує інформацію, яка може бути використана в будь-яких спробах вторгнення.
Version 2використовує користувачів UIDабо GIDdomian, 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 є абсолютно непрозорими, і саме так і має бути.
Ви можете мати один стовпчик як основний ключ з a, UUIDа потім ви можете мати складні унікальні індекси для того, що було б природним складеним первинним ключем.
Зберігання теж не повинно бути CHAR(36). Ви можете зберігати UUIDв рідному байті / біті / полі числа для даної бази даних, поки вона все ще індексується.
Спадщина
Якщо у вас є вихідні типи і ви не можете їх змінити, ви все одно можете їх абстрагувати у своєму коді.
Використання Version 3/5з UUIDвас може пройти в Class.getName()+ String.valueOf(int)вигляді byte[]і має непрозорий контрольний ключ , який recreatable і детерміновані.