如何用实体经理管理反序列化实体? [英] How to manage deserialized entities with entity manager?

查看:131
本文介绍了如何用实体经理管理反序列化实体?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



例如,此模式:

 类订单
{
private $ id;

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

类项目
{

private $ id;

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

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

}

映射到此json: { id:1,items:[{id:1,amount:100},{id:2,amount:200}]} json被正确地反序列化为类型为 MyBundle:Order 的对象,它具有两个 MyBundle:Order / Item 对象的集合。



问题是当我尝试保留此对象时,会在数据库中创建新条目,而不是更新现有的,忽略ids。如何告知实体经理这些对象应该更新,而不是创建?



更新。一般来说EntityManager :: merge解决方案(由DaveM建议)很好。但是,您必须只合并现有对象。例如,如果您有一个json表示连接到现有Order\Item实体的新Order实体


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


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

解决方案

您需要使用 merge作为合并实体的 EntityManager 中的()方法是指将实体合并到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


I am using JMSSerializerBundle to serialize my entities to json and deserialize json into entities, but I think this question applies for any deserialization techniques.

For example, this schema:

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;

}

Maps to this json: {"id":1,"items":[{"id":1,"amount":100}, {"id":2,"amount":200}]} and the same json is properly deserialized into an object of type MyBundle:Order that has a colletion of two MyBundle:Order/Item objects.

The problem is that when I try to persist this object, new entries are created in the database, rather than updating existing, ignoring the ids. How do I tell entity manager that theses objects should be updated, rather that created?

Update. Generally EntityManager::merge solution (as suggested by DaveM) is fine. But you must only merge existing objects. For example, if you have a json that represents a new Order entity that is connected to existing Order\Item entities

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

In this case you cannot just merge an Order object like this: $em->merge($order), because order is a new entity and entity manager will attempt to find an Order object with id = null and you will end up with a new Order and empty items array. So the solution is to loop the Order::$items array and merge each item individually. Then a new order will be created and connected with existing items.

解决方案

You need to use the merge() method on the EntityManager as merging entities refers to the merging of entities into the context of an EntityManager so that they can become managed again. In order to merge the state of an entity into an EntityManager use the EntityManager#merge($entity) method. The state of the passed entity will be merged into a managed copy of this entity and this copy will subsequently be returned.

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

Also be sure to note when you want to serialize/unserialize entities you have to make all entity properties protected, never private. The reason for this is, if you serialize a class that was a proxy instance before, the private variables won’t be serialized and a PHP Notice is thrown.

More information can be found in the doctrine documentation here:

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

这篇关于如何用实体经理管理反序列化实体?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆