EntityManager 已关闭?

Posted

技术标签:

【中文标题】EntityManager 已关闭?【英文标题】:The EntityManager is closed? 【发布时间】:2019-02-22 03:00:12 【问题描述】:

我在第 167 行遇到错误,它告诉我 我使用了 symfony2 和 aurelia。 我放了“processUserDetails”来完成它。

 private function processUserDetails($library, $entity, $oldDetails, $settings) 
        $newDetails = $entity->getDetails();
        $em = $this->getDoctrine()->getManager();

        $this->disableBlameableEventListeners($em);

        foreach($oldDetails as $detail) 
            if(!$newDetails->contains($detail)) 
                $library->removeResource($detail->getResource());
                $em->remove($detail);
            
        

        $em->flush();
        $this->enableBlameableEventListeners($em);

        foreach($newDetails as $detail)
            if(!$detail->getId()) $em->persist($detail);

        $em->flush();

        foreach($newDetails as $detail) 
            $resource = $detail->getResource();

            if(!$library->getResources()->contains($resource))
                $library->addResource($resource);
        
        $em->flush();
        if($this->getUser() === $entity->getUser()) 
            $this->putMembershipContactSetting($entity, $settings);
            $locale = $entity->getLocale();

            if($locale && $entity->getUser()->getLocale() !== $locale)
                $this->setUserLocale($entity);

            $em->flush();
        
    

 public function putMembershipAction(Request $request, Company $company, Membership $entity) 
        if(!$this->canTouchIt($company, 'RolesManage') && $this->getUser() !== $entity->getUser())
            return FOSView::create('Unauthorized', Codes::HTTP_UNAUTHORIZED);

        $em = $this->getDoctrine()->getManager();
        $settings = $request->request->get('contact_settings');

        $request->setMethod('PATCH');
        $library = $entity->getAssets();

        $form = $this->createForm(
            new MembershipType($this->isAdminUser()), $entity,
            array('method' => $request->getMethod())
        );

        $oldDetails = $entity->getDetails();
        $entity->setDetails(new ArrayCollection);

        $this->removeExtraFields($request, $form);
        $form->handleRequest($request);



        if($form->isValid()) 

            if($entity->getPermissions())
                $entity->getPermissions()->setMembership($entity);

            if($entity->getStatus() === Membership::STATUS_ACCEPTED)
                $this->processUserDetails($library, $entity, $oldDetails, $settings);

            $this->get('desygner_brand.membership.manager')
                ->addMemberToGlobalGroup($entity);

            $serializer = $this->get('jms_serializer');
            $context = SerializationContext::create()->setGroups(array('membership'));
            $this->get('monolog.logger.behaviour')->error('Company log #'.$company->getId(), array(
                'type' => 'Modify memeber',
                'user' => $this->getUser()->getId(),
                'data' => json_decode($this->get('jms_serializer')
                    ->serialize($entity, 'json', $context), true
                ),
            ));

            return $entity;
        

        return FOSView::create(array('errors' => $form->getErrors()), Codes::HTTP_PRECONDITION_FAILED);
    

我在第 167 行遇到错误,它告诉我 我用过 symfony2 和 aurelia ,我把“processUserDetails”放在里面。

有人可以帮帮我吗?

【问题讨论】:

我猜 EntityManager 负责连接到数据库并用它做一些事情。而且您太早地完成了函数调用并终止了数据库的连接。上面的代码块中是否有任何需要等待的异步内容? @bigopon,不,你能检查一下进程用户详细信息中的fluch()吗?我认为是问题所在,但我不知道它的正确位置 哦,是的,这应该是问题所在。您的 flush() 导致连接关闭。这就是错误的原因。你应该只把它放在最后。它来自哪里。 @bigopon 哪个不正确?我不知道应该把fluch放在哪里? 【参考方案1】:

您在processUserDetails 中刷新得太早了。它需要重构方法/类以确保在适当的时间调用flush()。一种快速的解决方法是让方法接受EntityManager 作为参数,以及一个可选参数来告诉它不要在最后刷新:

private function processUserDetails($em, $library, $entity, $oldDetails, $settings, $doNotFlush) 
    $newDetails = $entity->getDetails();

    $this->disableBlameableEventListeners($em);

    foreach($oldDetails as $detail) 
        if(!$newDetails->contains($detail)) 
            $library->removeResource($detail->getResource());
            $em->remove($detail);
        
    

    // flushing too early ?
    // $em->flush();
    $this->enableBlameableEventListeners($em);

    foreach($newDetails as $detail)
        if(!$detail->getId()) $em->persist($detail);

    // flushing too early ?
    // $em->flush();

    foreach($newDetails as $detail) 
        $resource = $detail->getResource();

        if(!$library->getResources()->contains($resource))
            $library->addResource($resource);
    
    // flushing too early ?
    // $em->flush();
    if($this->getUser() === $entity->getUser()) 
        $this->putMembershipContactSetting($entity, $settings);
        $locale = $entity->getLocale();

        if($locale && $entity->getUser()->getLocale() !== $locale)
            $this->setUserLocale($entity);

        // flushing too early ?
        $em->flush();
    

    if (!doNotFlush) 
        $em->flush();
    

然后在你的putMembershipAction()

if($entity->getStatus() === Membership::STATUS_ACCEPTED)
    $this->processUserDetails($em, $library, $entity, $oldDetails, $settings, true);

// .... 


// before return, flush it
$em->flush();
// now returns
return $entity;

请注意,这样做会改变您的 processUserDetails 的工作方式,您应该重新验证流程。关键是将每个实体都保存在内存中,最后只调用一次flush()

【讨论】:

以上是关于EntityManager 已关闭?的主要内容,如果未能解决你的问题,请参考以下文章

EntityManager 已关闭?

注入 EntityManager 与。实体管理器工厂

播放框架:EntityManager 已关闭

EntityManagerFactory 和 SessionFactory 的区别? [复制]

我们是不是需要在选择调用时关闭 EntityManager 资源

我必须关闭()每个 EntityManager 吗?