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

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

问题描述

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

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.

例如,这个架构:

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;

}

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

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.

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

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?

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

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}]}

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

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

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.

推荐答案

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

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);

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

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://学说-orm.readthedocs.org/en/2.0.x/reference/working-with-objects.html#merging-entities

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

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