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 已关闭?的主要内容,如果未能解决你的问题,请参考以下文章
EntityManagerFactory 和 SessionFactory 的区别? [复制]