Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
497 views
in Technique[技术] by (71.8m points)

serialization - How to manage deserialized entities with entity manager?

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;

    /**
     * @SerializerType("ArrayCollection<MyBundleEntityOrderItem>")
     * @ORMOneToMany(targetEntity="MyBundleEntityOrderItem", mappedBy="order", cascade={"persist"})
     */
    private $items;
}

class Item
{

    private $id;

    /**
     * @ORMManyToOne(targetEntity="MyBundleEntityOrder", inversedBy="items")
     */
    private $order;

    /**
     * @var integer $amount
     * @SerializerType("integer")
     * @ORMColumn(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 OrderItem 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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...