我正在研究一个基于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的实体,我可以检查每个接收到的对象。在这种情况下,可以加载现有对象并手动更新其属性。但是,这将非常麻烦。实际的项目当然会使用许多不同的实体,并且每个实体类型/类都需要使用自己的处理方法来检查哪些属性需要更新。有没有更好的解决方案?
答案 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