Почему существует необходимость отсоединения и объединения объектов в ORM?
Вопрос о Doctirne, но я думаю, что это может быть распространено на многие ORM.
Detach:
Сущность отделяется от EntityManager и, следовательно, больше не управляется путем вызова метода EntityManager#detach($entity)
на нем или путем каскадируя операцию отсоединения к ней. Изменения, внесенные в отдельные субъект, если таковой имеется (включая удаление объекта), не будет синхронизируется с базой данных после отсоединения объекта.
Merge:
Объединяющие объекты относятся к объединению (обычно отделяемых) объектов в контексте EntityManager, чтобы они стали управляемыми еще раз. Чтобы объединить состояние объекта в EntityManager, используйте EntityManager#merge($entity)
. Состояние переданного объекта будут объединены в управляемую копию этого объекта, и эта копия будет впоследствии возвращаются.
Я понимаю (почти), как это работает, но вопрос в том, почему нужно отделить/слияния? Можете ли вы привести пример/сценарий, когда эти две операции могут быть использованы/необходимы?
Ответы
Ответ 1
Когда мне нужно отсоединить объект?
Отсоединение объекта от EM (EntityManager) широко используется, когда вы имеете дело с несколькими EM и избегаете конфликтов concurrency, например:
$user= $em->find('models\User', 1);
$user->setName('Foo');
// You can not remove this user,
// because it still attached to the first Entity Manager
$em2->remove($user);
$em2->flush();
Вы не можете взять под контроль объект $user
$em2
, потому что его сеанс принадлежит $em
, который первоначально загружает $user
из базы данных. Их как решить проблему выше? Вам необходимо отделить объект:
$user= $em->find('models\User', 1);
$user->setName('Foo');
$em2->detach($user);
$em2->remove($user);
$em2->flush();
Когда следует использовать функцию слияния?
В основном, если вы хотите обновить объект:
$user= $em->find('models\User', 1);
$user->setName('Foo');
$em->merge($user);
$em->flush();
EM проведет сравнение между $user в базе данных и $user в памяти. Как только EM распознает измененные поля, он только обновляет их и сохраняет старые.
Метод flush
запускает фиксацию, и имя пользователя будет обновляться в базе данных
Ответ 2
Вам нужно будет отключить объект при работе с проблемами concurrency.
Предположим, вы используете асинхронный API, который делает обратные вызовы для вашего проекта. Когда вы выдаете вызов API вместе с инструкцией обратного вызова, вы все равно можете управлять объектом, на который влияет обратный вызов, и, следовательно, перезаписывать изменения, сделанные обратным вызовом.
Ответ 3
Вы также можете отключить объект, когда у вас есть данные, хранящиеся в вашей базе данных, но в вашем коде вы изменяете эти объекты в зависимости от учетной записи пользователя.
Например, браузерная игра, в которой есть некоторые персонажи и некоторые атаки для борьбы. AttackOne, используемый "UserFoo" (lvl 90), будет изменен лучшими бонусами, чем используется "UserBarr" (lvl 20), но в нашей базе AttackOne все время та же атака