术后冲洗是否可以坚持?

问题描述 投票:0回答:2

我已阅读有关生命周期事件的文档,以及有关在生命周期事件期间更改或保留新实体的几个问题。打电话

EnitityManager::flush()
好像有问题。

好的,但是仔细查看文档,有一个代码示例,其中在postPersist中更改了字段,但没有调用flush。

我检查了这一点,建议的更改是not写入数据库。只有被持久化的对象才会收到更改。

<?php

/** @Entity @HasLifecycleCallbacks */
class User
{
    // ...

    /**
     * @Column(type="string", length=255)
     */
    public $value;


    /** @PostPersist */
    public function doStuffOnPostPersist()
    {
        $this->value = 'changed from postPersist callback!';
    }
}

也许应该将其添加到文档中。我一开始就被误导了。

但是,当添加 LifecyleEventArgs 参数并刷新包含的 EntityManager 时,它们将被写入 DB:

/** @PostPersist */
public function doStuffOnPostPersist(LifecycleEventArgs $args)
{
    $this->value = 'changed from postPersist callback!';
    $args->getEntityManager()->flush(); // works in my tests. Is this safe to use ?

}

我不知道如何解释文档关于是否可以在postPersist内调用

flush

如您所见,我正在寻找一种可靠的方法来在插入或更新实体后对其执行某种后处理。我必须使用 postPersist,因为我需要自动生成的主键值。

附带问题:如果是,可以刷新,那么我是否可以在 PostUpdate 中保留其他对象?像这样:

 /** @PostPersist */
public function doStuffOnPostPersist(LifecycleEventArgs $args)
{
    $this->value = 'changed from postPersist callback!';
    $obj = new OtherObject("value " . $this->value);
    $args->getEntityManager()->persist($obj);
    $args->getEntityManager()->flush(); // works in my tests. Is this safe to use ?

}

边问:我已经尝试了最后一个变体,它似乎有效。但它是否有效,或者我是否可能创建深度递归堆栈?根据文档,postPersist代码被称为duringflush,所以如果我在postPersist期间调用flush,我必须小心不要持久化执行相同处理程序的对象,这将导致无限递归。这是正确的吗?

symfony doctrine-orm doctrine
2个回答
6
投票

我检查过,建议的更改未写入数据库。只有被持久化的对象才会收到更改。

也许应该将其添加到文档中。我一开始就被误导了。

文档中的代码不会尝试保留对 value 属性的修改 在数据库中,这就是为什么没有调用

flush()
的原因。它只是显示一个示例,该值也可以是未映射到类
User
的数据库属性。

我不知道如何解释有关是否可以在 postPersist 中调用flush的文档。

可以在 PostPersist 生命周期回调上调用

flush()
来更改映射的属性 您的实体的。在 PostPersist 回调中,您的实体已插入数据库中。通过改变属性 value 并调用
flush()
您的实体将被标记为要更新,因此 PostPersist 事件不会 再次调度(而不是调度 Pre/PostUpdate 事件)。

附带问题:如果是,可以刷新,那么我可以在 PostUpdate 中保留其他对象吗?

在PostPersist事件回调中持久化另一个实体类的新对象也是可以的,没有问题, 但是如果您尝试在此 PostPersist 回调中保留同一(用户)类的对象,您将得到一个 无限递归,你很容易理解。

侧问:我已经尝试了最后一个变体,它似乎有效。但它是否有效,或者我是否可能创建深度递归堆栈?

正如我之前所解释的,如果不保留回调所属的同一类(用户)的对象,则此代码不会创建太深的递归堆栈或无限循环。

flush()
将被调用两次。尽管在处理关联时事情可能会变得更加复杂,但在您的示例中不存在这样的问题。


0
投票

这是可能的,但文档建议不要这样做。

强烈建议不要对实体进行更改并从 EntityManager::flush() 本身调度的事件处理程序中调用 EntityManager::flush(),并且将来可能会被弃用并最终被阻止。

或者,您可以创建一个收听

postPersist
onClear
的订阅者。在
postPersist
期间,您可以将对象(或其 id)聚合到订阅者类上设置的属性中。在
onFlush
期间,您可以访问相同的属性并刷新(或查找)对象,并执行所需的操作。

© www.soinside.com 2019 - 2024. All rights reserved.