在 postPersist 事件中插入 Doctrine [英] Doctrine inserting in postPersist event

查看:16
本文介绍了在 postPersist 事件中插入 Doctrine的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在实体持久化和更新上添加新的 Feed 项.我写了这个事件监听器(postUpdate 是一样的):

I want add new Feed item on entity persist and update. I write this event listener (postUpdate is same):

public function postPersist(LifecycleEventArgs $args)
{
    $entity = $args->getEntity();
    $em = $args->getEntityManager();

    if ($entity instanceof FeedItemInterface) {
        $feed = new FeedEntity();
        $feed->setTitle($entity->getFeedTitle());
        $feed->setEntity($entity->getFeedEntityId());
        $feed->setType($entity->getFeedType());
        if($entity->isFeedTranslatable()) {
            $feed->getEnTranslation()->setTitle($entity->getFeedTitle('en'));
        }
        $em->persist($feed);
        $em->flush();
    }
}

但是我得到了

违反完整性约束:1062 密钥重复条目30-2"'主要'

Integrity constraint violation: 1062 Duplicate entry '30-2' for key 'PRIMARY'

并且在日志a中有两个插入:

and in log a have two insertations:

INSERT INTO interview_scientificdirection (interview_id,sciencedirection_id) VALUES (?, ?) ([30,2]) INSERT INTO采访_科学方向(采访_id,科学方向_id)值 (?, ?) ([30,2])

INSERT INTO interview_scientificdirection (interview_id, scientificdirection_id) VALUES (?, ?) ([30,2]) INSERT INTO interview_scientificdirection (interview_id, scientificdirection_id) VALUES (?, ?) ([30,2])

scientificdirection 是我们想要持久化的实体的多对多关系表.在前端应用程序中一切正常,但在 Sonata Admin 中我遇到了这个问题:(

scientificdirection is Many to Many relationship table for entity what we want to persist. In frontend application everything work fine, but in Sonata Admin I got this problem :(

推荐答案

如果您需要持久化其他对象,遗憾的是,Doctrine 中的 postPersist 或 postUpdate 处理程序不是正确的选择.今天我遇到了同样的问题,因为我需要在该处理程序中生成一些消息条目.

If you need to persist additional objects, the postPersist or postUpdate handler in Doctrine is, sadly, not the right place to go. I struggled with the same problem today, as I needed to generate some message entries in that handler.

此时的问题是 postPersist 处理程序在刷新事件期间调用,而不是之后调用.所以你不能在这里持久化额外的对象,因为它们之后不会被刷新.此外,您不能在 postPersist 处理程序期间调用flush,因为这可能会导致重复条目(正如您所经历的那样).

The problem at this point is that the postPersist handler is called during the flush event, and not after. So you can't persist additional objects here, as they are not getting flushed afterwards. Additionally, you can't call flush during an postPersist handler, as this might lead to ducplicate entries (as you have experienced).

一种方法是使用来自学说的 onFlush 处理程序,记录在此处:https://www.doctrine-project.org/projects/doctrine-orm/en/2.7/reference/events.html#onflush

One way to go is using the onFlush handler from doctrine, documented here: https://www.doctrine-project.org/projects/doctrine-orm/en/2.7/reference/events.html#onflush

如果您需要插入的数据库对象的 id,这只是有问题,因为实体尚未在该处理程序中写入数据库.如果您不需要这些 id,那么您可以使用准则中的 onFlush 事件.

This is just problematic if you need the inserted ids of the database object, as the entity hasn't yet been written to the database in that handler. If you don't need those ids, you are fine with the onFlush event in doctrine.

对我来说,解决方案有点不同.我目前正在处理一个 symfony2 项目,需要插入的数据库对象的 id(用于稍后的回调和更新).

For me, the solution was a little different. I'm currently working on a symfony2 project, and needed the ids of the inserted database objects (for callbacks and updates later on).

我在 symfony2 中创建了一个新服务,它基本上就像我的消息队列一样.在 postPersist 更新期间,我只填写队列中的条目.我在 kernel.response 上注册了另一个处理程序,然后它将这些条目保存到数据库中.(大致如下:http://symfony.com/doc/current/cookbook/service_container/event_listener.html)

I created a new service in symfony2, which basically just acts like a queue for my messages. During the postPersist update, I just fill the entries in the queue. I have another handler registered on kernel.response, which then takes those entries and persists them to the database. (Something along the line of this: http://symfony.com/doc/current/cookbook/service_container/event_listener.html)

我希望我不要离题太多,但由于这是我真正挣扎的事情,我希望有些人可能会觉得这很有用.

I hope I don't digress too much from the topic here, but as it is something I really struggled with, I hope that some people might find this useful.

此服务条目是:

 amq_messages_chain:
   class: AcmeStoreBundleListenerAmqMessagesChain

 amqflush:
   class: AcmeStoreBundleListenerAmqFlush
   arguments: [ @doctrine.orm.entity_manager, @amq_messages_chain, @logger ]
   tags:
     - { name: kernel.event_listener, event: kernel.response, method: onResponse, priority: 5 }

 doctrine.listener:
  class: AcmeStoreBundleListenerAmqListener
  arguments: [ @logger, @amq_messages_chain ]
  tags:
    - { name: doctrine.event_listener, event: postPersist }
    - { name: doctrine.event_listener, event: postUpdate }
    - { name: doctrine.event_listener, event: prePersist }

您不能为此使用 doctrine.listener,因为这会导致循环依赖(因为您需要服务的实体管理器,但实体管理器需要服务....)

You can't use the doctrine.listener for this, as this leads to a circular dependency (as you need the entity manager for the service, but the entity manager needs the service....)

这很有魅力.如果您需要更多相关信息,请随时提问,我很乐意为此添加一些示例.

That worked like a charm. If you need more info on that, don't hesitate to ask, I'm glad to add some examples to this.

这篇关于在 postPersist 事件中插入 Doctrine的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆