与实体管理器多次合并后,Symfony/Doctrine实体会导致脏实体关联

标签 symfony serialization doctrine-orm

我正在使用Symfony2和Doctrine

我有一个理论实体,该实体被序列化/反序列化为一个 session ,并在多个屏幕中使用。该实体具有多个一对多的关联。

该学说实体具有以下一对多的特征,例如:

class Article {

...

    /**
     * @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;
    }

我可以多次保存实体并将其加载到 session 中或从 session 中加载实体,然后将其合并回实体管理器并保存。仅当它是一个新实体时。

但是,一旦我从数据库加载了一个实体,然后将其保存到 session 中,就会遇到问题。

我从其他帖子中知道,在对保存的实体进行反序列化之后,必须运行$ em-> merge($ entity);。

我能够合并实体,添加一个新的子实体(一对多),然后保存:
$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

但是,在第一次合并和图像添加之后,我无法再添加任何子实体。如果我尝试添加第二个图像,它将返回以下错误:
A managed+dirty entity <<namespace of entity>>
image@0000000067078d7400000000221d7e02 can not 
be scheduled for insertion.

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

有人知道为什么实体会被标记为肮脏吗?我是否需要重置实体本身,如果要重置,我该怎么做?

最佳答案

知道了。

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

您不能合并具有非持久子实体的实体。它们被标记为脏的。

IE

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

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

如果您保存将文章序列化为 session ,然后将其反序列化并合并。没关系。

如果添加新图像,然后将其序列化为 session ,则会遇到问题。这是因为您无法合并非持久实体。
ARTICLE (ID 1) -> IMAGE (ID 1)
               -> IMAGE (ID 2)
               -> IMAGE (NOT YET PERSISTED)

我要做的是:

对文章进行反序列化之后,我将删除未持久化的图像并将其存储在一个临时数组中(我检查ID)。然后,我将文章合并,然后重新添加非持久图像。
        $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;                        

然后,如果需要,我可以添加更多图像,并重复该过程,直到最终将文章重新提交给DB。

如果您需要执行多页创建过程或通过AJAX添加图像,这很容易知道。

关于与实体管理器多次合并后,Symfony/Doctrine实体会导致脏实体关联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13714242/

相关文章:

php - 谷歌索引 API - 403 'Forbidden Response'

php - Symfony2 查找重复行并对另一列求和

performance - 如何使 Symfony2 使用连接 : Keep-Alive? 返回 HTTP 响应

java - 序列化 Collat​​or 实例

php - 在 Symfony2 中创建数据库

php - 如何将 GROUP_BY 与查询构建器和 mySQL >= 5.7 一起使用?

c++ - boost::serialize 和 std::chrono::system_clock::time_point

c++ - 静态成员和 boost 序列化

mysql - Doctrine 2 : is multiple level STI possible?

mysql - Symfony 4 Doctrine 多个表连接在一个属性中