3

Мы имеем несколько агрегатных корни, которые имеют два основных средства идентификации:Как неустойчивость настойчивости работает со ссылками на (не-корневые) агрегаты?

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

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

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

Как можно обойти эту проблему или есть недостаток в моем понимании невежества настойчивости?

EDIT относительно строки на основе идентификаторов

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

class Customer { 
    public function __construct($customerKey, $customerId, $name) { 
     $this->customerKey = $customerKey; 
     $this->customerId = $customerId; 
     $this->name = $name; 
    } 
} 

function test(Repository $repository, UnitOfWork $unitOfWork) { 
    $customer = new Customer(0, $repository->generateCustomerId(), "John Doe"); 
    // $customer->customerKey == 0 
    $unitOfWork->saveCustomer($customer); 
    // $customer->customerKey != 0 
} 

Я полагаю, что та же концепция может быть использована для создания объекта с целочисленным на основе ключа не-0, и единица работы может использовать тот факт, что не существует в база данных как причина для INSERT, а не UPDATE. test() функция выше стали бы тогда:

function test(Repository $repository, UnitOfWork $unitOfWork) { 
    $customer = new Customer($repository->generateCustomerKey(), $repository->generateCustomerId(), "John Doe"); 
    // $customer->customerKey != 0 
    $unitOfWork->saveCustomer($customer); 
    // $customer->customerKey still != 0 
} 

Однако, учитывая выше, ошибки могут возникнуть, если единица работы не сохраняет объекты БД в правильном порядке. Можно ли обойти это, чтобы гарантировать, что Единица работы сохраняет объекты в правильном порядке?

Я надеюсь, что приведенное выше изменение разъясняет мою ситуацию.

+0

«в этих объектах нельзя ссылаться на другие совокупные корни до тех пор, пока они не будут сохранены» - я мог бы интерпретировать это несколькими разными способами, возможно, вы нарушаете границы своих совокупных корней? Кроме того, почему бы не моделировать ваши отношения как ссылки - тогда ваш граф объекта действителен независимо от того, сохранен ли id. См. Также: https://lostechies.com/jimmybogard/2008/05/21/entities-value-objects-aggregates-and-roots/ – Nathan

+0

«Почему бы не моделировать ваши отношения как ссылки», вы имеете в виду (C-стиль указатель-тип) ссылки? Например, вместо хранения ключа на основе целого, сохраняя указатель/ссылку на объект? Если это так, то загрузка одного агрегата будет означать загрузку значительной части «графа объектов», что нецелесообразно по соображениям производительности и размывает линии владения. – magnus

ответ

2

Это хороший подход, чтобы посмотреть на Агрегаты как границы последовательности. Другими словами, два разных агрегата имеют отдельные жизненные циклы, и вы должны воздерживаться от привязки их судьбы вместе внутри одной транзакции. Из этой аксиомы вы можете с уверенностью утверждать, что ни один из агрегатов A никогда не будет иметь идентификатор 0, если смотреть с другой точки зрения совокупности B, потому что либо транзакция, которая создает A, еще не закончена, и она не видна B или завершена и A имеет идентификатор.

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

+0

Этот ответ имеет большой смысл в зависимости от того, как я понимаю DDD, но текущее задание, над которым я работаю, связано с массовым созданием и обновлением значительного числа агрегатов и отношений на основе большого файла данных. Существует два этапа - проверка и подача. Правила проверки требуют наличия отношений, но если данные недействительны, обновление не будет продолжено. Поскольку агрегированные отношения зависят от не-0 ключей, а не-0 ключей зависят от стойкости базы данных, я не знаю, как я могу «воздерживаться от привязки своих суждений вместе внутри одной и той же транзакции». – magnus

+0

Не будет ли посредником 'Save() '' в ходе вашего UoW решить проблему? – guillaume31

+1

@ user1420752 Если вы объяснили деловую проблему, а не ограничили себя конкретным техническим подходом, возможно, мы могли бы помочь вам лучше. – plalx

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