当与实体经理多次合并时,Symfony / Doctrine实体导致肮脏的实体关联 [英] Symfony/Doctrine entity leads to dirty entity association when merged multiple times with entity manager

查看:105
本文介绍了当与实体经理多次合并时,Symfony / Doctrine实体导致肮脏的实体关联的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Symfony2和Doctrine



我有一个将序列化/非序列化到会话并在多个屏幕中使用的教义实体。这个实体有一对多的关联。



这个学说实体有以下一对多,例如:

 类文章{

...

/ **
* @ ORM\OneToMany(targetEntity =image,mappedBy =article,cascade = {merge,detach,persist})
* /
protected $ images;

public function __construct()
{
$ this-> images = new ArrayCollection();
}

.....
}

文章实体被保存和检索如下:

  public function saveArticle($ article)
{
$ articleSerialized = serialize($ article);
$ this-> session-> set('currentArticle',$ articleSerialized);
}

public function getArticle()
{
$ articleSerialized = $ this-> session-> get('currentArticle');
$ article = unserialize($ articleSerialized);
$ article = $ this-> em-> merge($ article);

return $ article;
}

我可以保存并加载实体到和从会话加载任何号码的时间,然后将其合并回实体管理器并保存。这只是一个新的实体。



然而,一旦我从数据库加载实体,然后将其保存到会话中,我会遇到问题。

我从其他帖子中知道,在您删除已保存的实体后,您必须运行$ em-> merge($ entity);



我可以合并实体,添加一个新的子实体(一对多),然后保存:

  $ article = $ this-> getArticle(); //上面声明,从会话中获取文章

$ image = new Image();
$ image-> setFilename('image.jpeg');
$ article-> addImage($ image);

$ this-> saveArticle($ article); //上面声明,将文章返回到会话

但是,在第一个合并和图像添加后,我无法再添加任何子实体。如果我尝试添加第二张图片,则会返回以下错误:

 托管+脏实体<<实体GT;> 
image @ 0000000067078d7400000000221d7e02不能
计划插入。

总而言之,我可以对实体进行任意数量的更改并将其保存到会话中,但是如果我在添加子实体时运行$ em->多次合并,则新的子实体被标记为脏。



有人知道为什么一个实体将标记为脏?我需要重置实体本身,如果是这样,我该怎么做?

解决方案

>

对于将来可能遇到此问题的任何人:



您不能合并具有不分配子实体的实体。它们被标记为脏。



IE



您可能有一篇文章,其中有两个图像已经保存到数据库。

  ARTICLE(ID 1) - > IMAGE(ID 1)
- > IMAGE(ID 2)

如果将文章序列化到会话,然后将其排序并合并。没关系。



如果你添加一个新的图像,然后序列化它到会话你将有问题。这是因为您无法合并一个不分配的实体。

  ARTICLE(ID 1) - > IMAGE(ID 1)
- > IMAGE(ID 2)
- > IMAGE(NOT YET PERSISTED)

我要做的是:



在我排除了文章的序列化之后,我删除了不分开的图像并将它们存储在一个临时数组中(我检查ID)。那么我合并了这篇文章,并重新添加了不分配的图片。

  $ article = unserialize($ this->会话级>获得( 'currentArticle')); 

$ tempImageList = array();

foreach($ article-> getImages()as $ image)
{
if(!$ image-> getId())//如果图像是新的,将其移动到临时数组
{
$ tempImageList [] = $ image;
$ article-> removeImage($ image);
}
}

$ plug = $ this-> em-> merge($ article); //现在可以合并实体

foreach($ tempImageList as $ image)
{
$ article-> addImage($ image); //将图像添加到新合并的插件中
}

return $ article;

然后,如果需要,我可以添加更多图像,并重复该过程,直到我终于坚持该文章到DB。



在您需要进行多页创建过程或通过AJAX添加图像的情况下,这是非常方便的。


I am using Symfony2 and Doctrine

I have a doctrine entity which is serialized/unserialized to a session and used in multiple screens. This entity has a number of one to many associations.

The doctrine entity has the following one to many, for example:

class Article {

...

    /**
     * @ORM\OneToMany(targetEntity="image", mappedBy="article", cascade=  {"merge","detach","persist"})
     */
    protected $images;

    public function __construct()
    {
        $this->images = new ArrayCollection();
    }

    .....
}

The article entity is saved and retrieved as follows:

    public function saveArticle($article)
    {
        $articleSerialized = serialize($article);
        $this->session->set('currentArticle',$articleSerialized);
    }

    public function getArticle()
    {
        $articleSerialized = $this->session->get('currentArticle');
        $article = unserialize($articleSerialized);
        $article = $this->em->merge($article);

        return $article;
    }

I am able to save and load the entity to and from the session any number of times, and then merge it back to the entity manager and save. This is only if it is a new entity.

However, once I load an entity from the db and then save it to session, I get problems.

I know, from other posts, that after you unserialise a saved entity, you have to run $em->merge($entity);

I am able to merge the entity, add a new sub-entity (one to many) and then save:

$article = $this->getArticle(); //Declared above, gets article from session

$image = new Image();
$image->setFilename('image.jpeg');
$article->addImage($image);

$this->saveArticle($article); //Declared above, returns the article to session

However, after the first merge and image add, I can't add any more sub-entities. If i try to add a second image, It returns the following error:

A managed+dirty entity <<namespace of entity>>
image@0000000067078d7400000000221d7e02 can not 
be scheduled for insertion.

So in summary, i can make any number of changes to an entity and save it to session, but if I run $em->merge more than once while adding sub-entities, the new sub-entities are marked as dirty.

Does anybody know why an entity would be marked as dirty? Do I need to reset the entity itself, and if so, how could I do that?

解决方案

Got it.

For anyone who might run into this problem in the future:

You cannot merge an entity which has unpersisted sub-entities. They become marked as dirty.

I.E

You may have an article with two images already saved to DB.

ARTICLE (ID 1) -> IMAGE (ID 1)
               -> IMAGE (ID 2)

If you save serialise the article to session and then unserialize and merge it. It's ok.

If you add a new image, then serialize it to session you will have problems. This is because you cannot merge an unpersisted entity.

ARTICLE (ID 1) -> IMAGE (ID 1)
               -> IMAGE (ID 2)
               -> IMAGE (NOT YET PERSISTED)

What I had to do was:

After I unserialize the article, I remove the unpersisted images and store them in a temporary array (I check for ID). THEN i merge the article and re-add the unpersisted image(s).

        $article = unserialize($this->session->get('currentArticle'));

        $tempImageList = array();

        foreach($article->getImages() as $image)
        {
            if(!$image->getId()) //If image is new, move it to a temporary array
            {
                $tempImageList[] = $image;
                $article->removeImage($image);
            }
        }

        $plug = $this->em->merge($article); //It is now safe to merge the entity

        foreach($tempImageList as $image)
        {
            $article->addImage($image); //Add the image back into the newly merged plug
        }

        return $article;                        

I can then add more images if need be, and repeat the process until I finally persist the article back to DB.

This is handy to know in the event you need to do a multiple pages creation process or adding images via AJAX.

这篇关于当与实体经理多次合并时,Symfony / Doctrine实体导致肮脏的实体关联的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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