Промывка в postPersist возможна или нет? - PullRequest
0 голосов
/ 22 сентября 2018

Я прочитал документы о событиях жизненного цикла и несколько вопросов здесь, посвященных SO, об изменении или сохранении новых сущностей во время событий жизненного цикла.Вызов EnitityManager::flush() кажется проблемой.

Хорошо, но , внимательно просматривая документы , есть пример кода, где поле изменяется в 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 ?

}

Я незнать, как интерпретировать документы о том, нормально или нет вызывать flush внутри postPersist.

Как видите, я ищу надежный способ выполнить какое-топостобработки моих сущностей после их вставки или обновления.Я должен использовать 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 называется во время flush, поэтому, если я вызываю flush во время postPersist, я должен быть осторожен, чтобы не сохранить объект, который выполняет тот же обработчик, что приведет к бесконечной рекурсии.Это правильно?

1 Ответ

0 голосов
/ 23 сентября 2018

Я проверил это, и предлагаемое изменение не записывается в БД.Только сохраняемый объект получает изменение.

Возможно, следует добавить это в документы.Сначала я вводил в заблуждение.

Код в документации не пытается сохранить эту модификацию свойства value в базе данных, поэтому не вызывается flush().Это просто показывает пример, и это значение также может быть сопоставлено со свойством базы данных класса User.

Я не знаю, как интерпретировать документы о том, нормально ли это или нетвызовите очистку внутри postPersist.

Можно вызвать flush() для обратного вызова жизненного цикла PostPersist, чтобы изменить сопоставленное свойство вашей сущности.В вашем обратном вызове PostPersist ваша сущность уже вставлена ​​в вашу базу данных.Изменяя значение свойства и вызывая flush(), ваша сущность будет помечена как подлежащая обновлению, поэтому событие PostPersist не будет отправлено снова (вместо этого будут отправлены события Pre / PostUpdate).

Дополнительный вопрос: Если да, то все в порядке, можно ли затем сохранить другие объекты в PostUpdate?

Также можно сохранить новый объект другого класса сущности в обратном вызове события PostPersist с помощьюнет проблем, но если вы попытаетесь сохранить объект того же (User) класса в этом обратном вызове PostPersist, у вас будет бесконечная рекурсия, как вы можете легко понять.

Дополнительный вопрос: Iперепробовал последний вариант, и похоже на работу.Но эффективно ли это, или я, возможно, создаю глубокие стеки рекурсии?

Как я объяснил ранее, этот код не создает слишком глубокие стеки рекурсии или бесконечные циклы, если не сохраняются объекты одного класса (Пользователь), которому принадлежит обратный вызов.flush() будет вызван ровно два раза.Хотя вещи могут усложняться, если иметь дело с ассоциациями, в вашем примере такой проблемы нет.

...