Сбросить только определенные объекты в одной транзакции
В моем приложении я пишу в таблицу чтения модели (например, CQRS) в определенное время. При этом я также должен удалить старые модели чтения. Так что в любой момент мне нужно:
- Удалить объекты a,b,c
- Персистирующие сущности x,y,z
Чтобы поддерживать правильную модель чтения на протяжении всего жизненного цикла, я хотел бы заключить этот процесс в одну транзакцию. Доктрина предоставляет необходимые средства.
Однако я также должен гарантировать, что никакие другие объекты не будут сброшены в процессе. К сожалению, называя доктрину $em->getConnection()->commit();
кажется, чтобы промыть всю единицу работы. Но согласно документам, я должен позвонить, чтобы завершить транзакцию.
Я не могу представить второго менеджера сущностей, который будет принимать только те объекты моей модели чтения, которые находятся в том же пространстве имен, что и другие сущности, и, очевидно, это не тот способ, которым предполагается использовать doctrine-orm-bundle.
Единственный другой подход, который я вижу, - это работать на более низком уровне и полностью обойти EntityManager и UnitOfWork, но я хотел бы гарантировать целостность транзакций и не вижу способа сделать это без em/ouw.
1 ответ
TLDR. То, как работает ваше приложение, может гарантировать, что проблемы обновления полностью разделяются на два независимых набора, но это необычно и хрупко (обычно даже не верно во время утверждения). Правильный способ моделирования, использующий отдельные EntityManager для каждого из наборов и защищающий их взаимосвязи вручную, - это семантика "как они независимы", закодированные в систему.
Подробности:
Если я правильно понимаю вопрос, вы столкнулись с недостатком дизайна здесь. У вас есть два набора обновлений (одно для моделей чтения и одно для других сущностей), и вы смешиваете их (потому что вы хотите оба в одном и том же диспетчере сущностей), а также хотите разделить их (с помощью отдельной транзакции), В общем, это не сработает.
Например, давайте подумаем, что экземпляр объекта не для модели чтения просто создан в памяти (поэтому у него еще нет идентификатора), и на основании этого вы решаете сослаться на него с экземпляром объекта модели чтения R. Отношение R->A допустимо в памяти, но теперь вы ожидаете, что сможете сбросить только чтение объектов модели, но не других. Т.е., когда вы попытаетесь сохранить + сбросить R, он будет ссылаться на несуществующий внешний ключ, и ваша СУБД, надеюсь, не выполнит транзакцию. На высокоуровневом уровне это связано с тем, что подключенный граф в памяти должен быть согласованным во всей полноте, а когда вы пытаетесь разделить его действительные изменения на подмножества, вы неявно меняете порядок этих изменений, что может привести к временной несогласованности. и тогда ваш транзакционный коммит может быть как раз в такой точке.
Конечно, может случиться так, что вы знаете какое-то правило, почему такого никогда не случится и почему согласованное состояние каждого набора гарантируется способом, который полностью независим от другого набора. Но тогда вам нужно написать свой код, отражающий это разделение; способ сделать это - использовать двух менеджеров сущностей. В этом случае ваш код будет четко справляться с двумя различными транзакциями, их разделением и насколько точно это будет согласовано с обеих сторон. Но даже в этом случае, чтобы избежать столкновений обновлений, вам, вероятно, нужно иметь правила, определяющие одностороннюю видимость между двумя наборами, что также подразумевает порядок совершения транзакций. Это связано с тем, что транзакции в связанном графе могут быть вложенными, но не "только перекрываться", потому что при каждой фиксации транзакции вы запрашиваете ORM синхронизировать согласованные данные в памяти области транзакции с RDBMS.
Я знаю, что вы упомянули, что вы не хотите использовать два EM, потому что объекты модели чтения "находятся в том же пространстве имен, что и другие объекты, и, очевидно, это не тот способ, которым предполагается использовать doctrine-orm-bundle".
- Пространство имен не имеет большого значения. Вы можете использовать их отдельно в двух менеджерах. Вы даже можете соединить их, если вы a) правильно слили () их и b) обеспечили вышеупомянутую согласованность, которую вы должны обеспечить для обеих транзакций EM (потому что теперь они работают на одном связанном графе).
- Вы должны прояснить, что именно вы имеете в виду, сказав: "это не тот способ, которым предполагается использовать комплект доктрины-нормы" - возможно, в исходном предложении есть ошибка или что-то не так с тем, как это предложение применяется к этому. проблема.