Doctrine 2 a EntityListener neproběhne v transakci

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Jiří Nápravník
Člen | 710
+
+1
-

Používám Doctrine a EntityListenery. Konkrétně tady dávám příklad na to, že po přidání či smazání položky chci updatovat počet odpovědí, na což jsou ideální EntityListenery. Jenže problém je, že když volám v tom EntityListeneru nějakou query s update, či pod. Tak se nepovede v transakci když zavolám $em->flush() ale po nebo před (podle toho jestli je to preEvent nebo postEvent) Jediným řešením je, když volám $em->remove(), tak to obalit do $em->transactional(), pak se proveodu pre i post eventy jak chci, ale není nějaké lepší řešní? Tohle je hodně blbý…

/**
 * @ORM\Entity
 * @ORM\EntityListeners({"DiscussionModule\Model\Entities\Listeners\DiscussionConversationListener"})
 */
class DiscussionConversation extends BaseEntity
{

    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type = "integer")
     */
    protected $id;

    /**
     * @ORM\Column(type = "text")
     */
    protected $text;

    /**
     * @ORM\Column(type = "integer")
     */
    protected $answersCount;
}
class DiscussionConversationListener
{

    /**
     * @ORM\PostPersist
     * @ORM\PostRemove
     */
    public function recountAnswersCount(DiscussionConversation $conversation, LifecycleEventArgs $event){
        $count = $event->getEntityManager()->createQuery('SELECT COUNT(c2.id) FROM ' . DiscussionConversation::getClassName() . ' c2 JOIN c2.user u '
                . 'WHERE c2.topic = :topic AND c2.mainTopic = FALSE')
            ->setParameter('topic', $conversation->getTopic())
            ->getSingleScalarResult();

        $qb = $event->getEntityManager()->createQueryBuilder();
        $qb->update(DiscussionConversation::getClassName(), 'c')
            ->set('c.answersCount', $count)
            ->where('c.topic = :topic AND c.mainTopic = TRUE')
            ->setParameter('topic', $conversation->getTopic())
            ->getQuery()
            ->execute();
    }
}
maryo
Člen | 15
+
0
-

https://github.com/…itOfWork.php#…
Tady začíná transakce.
Takže to můžeš zkusit při onFlush celý obalit ještě do jedný přímo z toho listeneru, tj. zavolat $entityManager->beginTransaction();.

a potom při postFlush transakci potvrdit pomocí $entityManager->commit();.

Vzhledem k tomu, že už nevoláš další flush (resp. další UnitOfWork::commit), tak by to (pokud mi něco neuniklo) teoreticky mělo jít.

Editoval maryo (19. 11. 2014 1:33)