【问题标题】:How to manage deserialized entities with entity manager?如何使用实体管理器管理反序列化实体?
【发布时间】:2012-06-28 03:06:44
【问题描述】:

我正在使用 JMSSerializerBundle 将我的实体序列化为 json 并将 json 反序列化为实体,但我认为这个问题适用于任何反序列化技术。

例如,这个架构:

class Order
{
    private $id;

    /**
     * @Serializer\Type("ArrayCollection<MyBundle\Entity\Order\Item>")
     * @ORM\OneToMany(targetEntity="\MyBundle\Entity\Order\Item", mappedBy="order", cascade={"persist"})
     */
    private $items;
}

class Item
{

    private $id;

    /**
     * @ORM\ManyToOne(targetEntity="\MyBundle\Entity\Order", inversedBy="items")
     */
    private $order;

    /**
     * @var integer $amount
     * @Serializer\Type("integer")
     * @ORM\Column(name="amount", type="integer")
     */
    private $amount;

}

映射到这个 json:{"id":1,"items":[{"id":1,"amount":100}, {"id":2,"amount":200}]} 并且相同的 json 被正确反序列化为一个类型为 MyBundle:Order 的对象,该对象具有两个 MyBundle:Order/Item 的集合> 对象。

问题是,当我尝试持久化此对象时,会在数据库中创建新条目,而不是更新现有条目,而忽略 id。我如何告诉实体管理器这些对象应该更新,而不是创建?

更新。通常 EntityManager::merge 解决方案(如 DaveM 建议的那样)很好。但您只能合并现有对象。例如,如果您有一个 json 表示一个新的 Order 实体,该实体连接到现有的 Order\Item 实体

{"id":null,"items":[{"id":1,"amount":100}, {"id":2,"amount":200}]}

在这种情况下,您不能像这样合并 Order 对象: $em-&gt;merge($order),因为 order 是一个新实体,并且实体管理器将尝试查找 id = null 的 Order 对象,最终您将得到一个新的 Order 和空 items 数组。所以解决方案是循环 Order::$items 数组并单独合并每个项目。然后将创建一个新订单并将其与现有项目相关联。

【问题讨论】:

    标签: serialization symfony doctrine-orm deserialization


    【解决方案1】:

    您需要在 EntityManager 上使用 merge() 方法,因为合并实体是指将实体合并到 EntityManager 的上下文中,以便它们可以再次被管理。为了将实体的状态合并到 EntityManager 中,请使用 EntityManager#merge($entity) 方法。传递的实体的状态将被合并到该实体的托管副本中,该副本随后将被返回。

    $detachedEntity = unserialize($serializedEntity); 
    $entity = $em->merge($detachedEntity);
    

    还请务必注意,当您想要序列化/反序列化实体时,您必须保护所有实体属性,而不是私有属性。这样做的原因是,如果你序列化一个之前是代理实例的类,私有变量将不会被序列化,并且会抛出一个 PHP 通知。

    更多信息可以在这里的学说文档中找到:

    http://doctrine-orm.readthedocs.org/en/2.0.x/reference/working-with-objects.html#merging-entities

    【讨论】:

      【解决方案2】:

      我知道这个问题已经存在三年了,但它误导我认为唯一的答案是使用合并操作。我想加两分钱:

      JMSSerializerBundle 包含一个用于 Doctrine 实体的对象构造函数。当您启用此构造函数时,反序列化的实体是可以持久化的托管实体(使用$em-&gt;persist($entity))。

      请查看this comment 以了解其他好处。 here 是您启用它的方法。

      【讨论】:

        猜你喜欢
        • 2019-01-27
        • 2014-07-15
        • 1970-01-01
        • 1970-01-01
        • 2019-11-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多