【问题标题】:Flushing in postPersist possible or not?是否可以在 postPersist 中刷新?
【发布时间】:2018-09-22 20:09:13
【问题描述】:

我已阅读有关生命周期事件的文档,以及关于 SO 在生命周期事件期间更改或保留新实体的几个问题。调用EnitityManager::flush() 似乎是个问题。

好的,但是looking carefully at the docs,有一个代码示例在 postPersist 中更改了字段,但没有调用刷新。

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

<?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 ?

}

我不知道如何interpret the docs 在 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 代码在刷新期间调用,所以如果我在 postPersist 期间调用刷新,我必须小心不要持久化执行相同处理程序的对象,这会导致无限递归.这是正确的吗?

【问题讨论】:

    标签: symfony doctrine-orm doctrine


    【解决方案1】:

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

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

    文档中的代码不会尝试保留对 value 属性的这种修改 在数据库中,这就是为什么没有调用 flush() 的原因。这只是一个例子,这个值也可以是一个未映射到类User的数据库属性。

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

    可以在 PostPersist 生命周期回调上调用 flush() 以更改映射属性 你的实体。在您的 PostPersist 回调中,您的实体已经插入到您的数据库中。通过更改属性 值并调用 flush() 您的实体将被标记为要更新,因此 PostPersist 事件不会 再次分派(而不是分派 Pre/PostUpdate 事件)。

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

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

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

    正如我之前解释的那样,如果不持久化回调所属的同一类(用户)的对象,此代码不会创建太深的递归堆栈或无限循环。 flush() 将被调用两次。虽然在处理关联时事情可能会变得更加复杂,但在您的示例中不存在这样的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-17
      • 1970-01-01
      • 1970-01-01
      • 2011-12-04
      • 2019-08-29
      • 2011-05-25
      • 2013-03-23
      • 2016-04-17
      相关资源
      最近更新 更多