我已经阅读了有关生命周期事件的文档,以及关于生命周期事件期间更改或持久化新实体的一些问题。呼叫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时,它们将被写入数据库:
/** @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期间调用flush,则必须注意不要持久执行同一处理程序的对象,这将导致无限递归。这是正确的吗?
答案 0 :(得分:3)
我检查了一下,建议的更改未写入数据库。仅持久化的对象会收到更改。
也许应该将其添加到文档中。起初我是误导人。
文档中的代码不会尝试保留对value属性的修改
这就是为什么没有调用flush()
的原因。只是显示一个示例,该值也可能未映射到类User
的数据库属性。
我不知道如何解释在postPersist内部调用flush是否可以的文档。
可以在PostPersist生命周期回调中调用flush()
来更改映射的属性
您的实体。在PostPersist回调中,您的实体已插入数据库中。通过更改属性
值并调用flush()
您的实体将被标记为要更新,因此PostPersist事件不会
再次调度(相反,将调度Pre / PostUpdate事件)。
侧面问题:如果可以,则可以冲洗,然后我还可以在PostUpdate中保留其他对象吗?
将另一个实体类的新对象持久保存在PostPersist事件回调中也是可以的, 但是,如果您尝试在此PostPersist回调中保留相同(用户)类的对象,则将有一个 您可以轻松理解的无限递归。
侧面问题:我尝试了最后一个变体,它似乎起作用。但这是否有效,或者我可能会创建深度递归堆栈?
正如我之前解释的那样,如果不持久保存回调所属的同一类(用户)的对象,则此代码不会创建太深的递归堆栈或无限循环。 flush()
将被精确调用两次。尽管在还要处理关联时事情可能会变得更加复杂,但是在您的示例中并没有这样的问题。