如何替换Doctrine 3中的EntityManager :: merge?

时间:2018-07-06 09:08:52

标签: symfony doctrine-orm

我正在研究一个基于Symfony 2.8的Web应用程序项目,该项目当前使用Doctrine 2。该项目基本上是一个简单的待办事项列表应用程序,可以与移动应用程序(iOS / Android)同步。

在阅读Doctrine 3的更新说明时,我发现EntityManager::merge will no longer be supported

  

ORM 3.0未提供EntityManager#merge()的替代方法,   因为合并语义应该是业务领域的一部分   而不是应用程序的持久域。如果你的   应用程序严重依赖类似于CRUD的交互和/或PATCH   宁静的操作,您应该查看诸如   JMSSerializer。

我不确定替换EntityManager::merge的最佳/正确方法是什么?

我在哪里使用合并:

在移动应用程序与Web应用程序同步期间,数据将作为序列化JSON传输,然后由JMSSerializer反序列化到实体对象。当Web应用以这种方式接收到ToDoEntry对象时,它可以是新的ToDo条目(Web应用中尚不知道)或更新的现有条目。无论哪种方式,接收到的对象都不由EntityManager管理。因此$em->persist($receivedObject)将始终尝试插入新对象。如果ToDo-Entry已存在于Web应用程序中并且需要更新,则将失败(由于id的唯一约束)。

使用$em->merge($receivedObject)来自动检查是否需要插入或更新。

热解决这个问题吗?

当然,如果已经存在具有相同ID的实体,我可以检查每个接收到的对象。在这种情况下,可以加载现有对象并手动更新其属性。但是,这将非常麻烦。实际的项目当然会使用许多不同的实体,并且每个实体类型/类都需要使用自己的处理方法来检查哪些属性需要更新。有没有更好的解决方案?

2 个答案:

答案 0 :(得分:0)

您可以尝试使用Doctrine \ ORM \ UnitOfWork的registerManaged()方法。

// $this->em <--- Doctrine Entity Manager
// $entity <--- detached Entity (and we know that this entity already exists in DB for example)

$id = [$entity->getId()];
$data = $entity->toArray();

$this->em->getUnitOfWork()->registerManaged($entity, array $id, array $data);

当然,在执行所需的操作之前/之后,您可以使用Doctrine \ ORM \ UnitOfWork的getEntityState()检查您的实体状态。

$this->eM->getUnitOfWork()->getEntityState($entity, $assert = 3)

$ assert <-如果NEW和DETACHED之间的区别对于方法的调用者来说是已知的或无关紧要的,则可以通过避免使用数据库查找来设置此参数,以提高实体状态检测的性能。

答案 1 :(得分:0)

实际上处理这个的代码可能只有几行。在后台 Doctrine 将发出一个查询来搜索您的实体(如果您的实体不在内存中),因此您可以通过启用结果缓存自己执行查询来执行相同的操作,然后只需使用 PropertyAccessor 来映射数据。

https://symfony.com/doc/current/components/property_access.html

查看此要点以了解 POC https://gist.github.com/stevro/99060106bbe54d64d3fbcf9a61e6a273