SYMFONY2 / DOCTRINE2在冲洗实体管理器时抛出索引错误



此处涉及三个实体:部署 declovementStep declovermentStatusLog 。我将首先粘贴这些类的相关定义

src/my/bundle/entity/deployment.php

<?php
namespace MyBundleEntity;
use DoctrineORMMapping as ORM;
use DoctrineCommonCollectionsArrayCollection;
use DoctrineORMPersistentCollection;
/**
 * @ORMTable(name="deployment")
 * @ORMEntity()
 */
class Deployment
{
  /**
   * Status Log Entries for this deployment
   *
   * @var DoctrineORMPersistentCollection
   *
   * @ORMOneToMany(targetEntity="DeploymentStatusLog", mappedBy="deployment", cascade={"persist","remove"})
   * @ORMOrderBy({"created_at"="DESC"})
   */
  protected $status_logs;
  /**
   * @var DoctrineORMPersistentCollection
   *
   * @ORMOneToMany(targetEntity="DeploymentStep", mappedBy="deployment", cascade={"persist","remove"})
   * @ORMOrderBy({"sequence" = "ASC"})
   */
  protected $steps;
  public function __construct()
  {
    $this->status_logs     = new ArrayCollection();
    $this->steps           = new ArrayCollection();
  }
  /**
   * Add status_logs
   *
   * @param DeploymentStatusLog $statusLogs
   */
  public function addDeploymentStatusLog(DeploymentStatusLog $statusLogs)
  {
      $this->status_logs[] = $statusLogs;
  }
  /**
   * Add steps
   *
   * @param DeploymentStep $steps
   */
  public function addDeploymentStep(DeploymentStep $steps)
  {
    $this->steps[] = $steps;
  }
  // ... 
}

src/my/bundle/entity/deploymentStep.php

<?php
namespace MyBundleEntity;
use DoctrineORMMapping as ORM;
/**
 * @ORMTable(name="deployment_step")
 * @ORMEntity()
 */
class DeploymentStep
{
  /**
   * @var Deployment
   *
   * @ORMManyToOne(targetEntity="Deployment", cascade={"all"})
   * @ORMJoinColumn(name="deployment_id", referencedColumnName="id")
   * @GedmoSortableGroup
   */
  private $deployment;
  /**
   * Set deployment
   *
   * @param Deployment $deployment
   */
  public function setDeployment(Deployment $deployment)
  {
    $this->deployment = $deployment;
  }
  // ...
}

src/my/bundle/entity/deploymentStatuslog.php

<?php
namespace MyBundleEntity;
use DoctrineORMMapping as ORM;
/**
 * @ORMTable(name="deployment_status_log")
 * @ORMEntity()
 */
class DeploymentStatusLog
{
  /**
   * @var Deployment
   *
   * @ORMManyToOne(targetEntity="Deployment", cascade={"all"})
   * @ORMJoinColumn(name="deployment_id", referencedColumnName="id", nullable=false)
   */
  protected $deployment;
  /**
   * Set deployment
   *
   * @param Deployment $deployment
   */
  public function setDeployment( Deployment $deployment)
  {
      $this->deployment = $deployment;
  }
  // ...
}

现在,当我尝试一次为所有这三个实体创建全新记录时,就会出现问题。在控制器中:

$em = $this->getDoctrine()->getEntityManager();
$deployment = new Deployment();
$form = $this->createForm(new DeploymentType($em), $deployment);
if ($request->getMethod() == 'POST')
{
  $form->bindRequest($request);
  if ($form->isValid())
  {
    $codeStep = new DeploymentStep();
    $codeStep->setDeployment( $deployment );
    // Other setters on DeploymentStep
    $deploymentStatusLog = new DeploymentStatusLog();
    $deploymentStatusLog->setDeployment( $deployment );
    // Other setters on DeploymentStatusLog
    $deployment->addDeploymentStep( $codeStep );
    $deployment->addDeploymentStatusLog( $deploymentStatusLog );
    $em->persist( $deployment );
    $em->flush();
  }
}

单位工程处理时会发生什么,它会抛出一个怪异的异常,抱怨不确定的索引:

异常" errorexception"带有消息'注意:未定义的索引: 000000001294F82200000000006B6F9F2C IN /project/vendor/doctrine/lib/doctrine/orm/unitofwork.php line 2252'in /project/vendor/symfony/src/symfony/component/httpkernel/debug/erorhandler.php:67

现在,如果我坚持/刷新部署 Entity,然后然后 persist/plassist/flush the关联,它将成功。

因此,虽然i can 这样做是为了使应用程序的这一部分起作用,但感觉有点错误,因为这个过程应该是原子,而且这就是全部要点从。

开始的交易查询

有线索?

  • Symfony 2.0.15
  • 学说2.1.7
  • php 5.3.3
  • mysql 5.1.52
  • Apache 2.2.15

编辑

通过请求的完整堆栈跟踪

 exception 'ErrorException' with message 'Notice: Undefined index: 000000004081f5f9000000005f1dbbfc in /project/vendor/doctrine/lib/Doctrine/ORM/UnitOfWork.php line 2252' in /project/vendor/symfony/src/Symfony/Component/HttpKernel/Debug/ErrorHandler.php:67
Stack trace:
#0 /project/vendor/doctrine/lib/Doctrine/ORM/UnitOfWork.php(2252): SymfonyComponentHttpKernelDebugErrorHandler->handle(8, 'Undefined index...', '/mnt/hgfs/mount...', 2252, Array)
#1 /project/vendor/doctrine/lib/Doctrine/ORM/Query.php(321): DoctrineORMUnitOfWork->getEntityIdentifier(Object(MyBundleEntityDeployment))
#2 /project/vendor/doctrine/lib/Doctrine/ORM/Query.php(274): DoctrineORMQuery->processParameterValue(Object(MyBundleEntityDeployment))
#3 /project/vendor/doctrine/lib/Doctrine/ORM/Query.php(243): DoctrineORMQuery->processParameterMappings(Array)
#4 /project/vendor/doctrine/lib/Doctrine/ORM/AbstractQuery.php(607): DoctrineORMQuery->_doExecute()
#5 /project/vendor/doctrine/lib/Doctrine/ORM/AbstractQuery.php(413): DoctrineORMAbstractQuery->execute(Array, 1)
#6 /project/vendor/gedmo-doctrine-extensions/lib/Gedmo/Sortable/SortableListener.php(344): DoctrineORMAbstractQuery->getResult()
#7 /project/vendor/gedmo-doctrine-extensions/lib/Gedmo/Sortable/SortableListener.php(133): GedmoSortableSortableListener->getMaxPosition(Object(DoctrineORMEntityManager), Object(DoctrineORMMappingClassMetadata), Array, Object(MyBundleEntityDeploymentStep))
#8 /project/vendor/gedmo-doctrine-extensions/lib/Gedmo/Sortable/SortableListener.php(100): GedmoSortableSortableListener->processInsert(Object(DoctrineORMEntityManager), Array, Object(DoctrineORMMappingClassMetadata), Object(MyBundleEntityDeploymentStep))
#9 /project/vendor/doctrine-common/lib/Doctrine/Common/EventManager.php(64): GedmoSortableSortableListener->onFlush(Object(DoctrineORMEventOnFlushEventArgs))
#10 /project/vendor/doctrine/lib/Doctrine/ORM/UnitOfWork.php(280): DoctrineCommonEventManager->dispatchEvent('onFlush', Object(DoctrineORMEventOnFlushEventArgs))
#11 /project/vendor/doctrine/lib/Doctrine/ORM/EntityManager.php(334): DoctrineORMUnitOfWork->commit()
#12 /project/src/My/Bundle/Controller/DeploymentController.php(214): DoctrineORMEntityManager->flush()
#13 [internal function]: MyBundleControllerDeploymentController->createAction(Object(MyBundleEntityRelease), Object(SymfonyComponentHttpFoundationRequest))
#14 /project/vendor/bundles/JMS/SecurityExtraBundle/Security/Authorization/Interception/MethodSecurityInterceptor.php(73): ReflectionMethod->invokeArgs(Object(MyBundleControllerDeploymentController), Array)
#15 /project/app/cache/dev/classes.php(9391) : eval()'d code(1): JMSSecurityExtraBundleSecurityAuthorizationInterceptionMethodSecurityInterceptor->invoke(Object(JMSSecurityExtraBundleSecurityAuthorizationInterceptionMethodInvocation), Array)
#16 [internal function]: {closure}(Object(MyBundleEntityRelease), Object(SymfonyComponentHttpFoundationRequest))
#17 /project/app/cache/dev/classes.php(3925): call_user_func_array(Object(Closure), Array)
#18 /project/app/cache/dev/classes.php(3895): SymfonyComponentHttpKernelHttpKernel->handleRaw(Object(SymfonyComponentHttpFoundationRequest), 1)
#19 /project/app/cache/dev/classes.php(4899): SymfonyComponentHttpKernelHttpKernel->handle(Object(SymfonyComponentHttpFoundationRequest), 1, true)
#20 /project/app/bootstrap.php.cache(551): SymfonyBundleFrameworkBundleHttpKernel->handle(Object(SymfonyComponentHttpFoundationRequest), 1, true)
#21 /project/web/app_dev.php(18): SymfonyComponentHttpKernelKernel->handle(Object(SymfonyComponentHttpFoundationRequest))
#22 {main}

编辑2

根据要求的创建操作的完整代码

/**
 * @Route("/create/{id}", name="deployment_create_id")
 * @ParamConverter("release", class="MyBundle:Release")
 * @Method({"POST","GET"})
 * @Secure(roles="ROLE_DEPLOYMENT_PLANNER")
 * @Template()
 */
public function createAction( Release $release, Request $request )
{
  $em           = $this->getDoctrine()->getEntityManager();
  $sessionUser = $this->get('security.context')->getToken()->getUser();
  $deployment = new Deployment();
  $deployment->setRelease( $release );
  $deployment->setAuthor( $sessionUser );
  $form = $this->createForm(new DeploymentType($em), $deployment);
  if ($request->getMethod() == 'POST')
  {
    $form->bindRequest($request);
    if ($form->isValid())
    {
      $codeStep = new DeploymentStep();
      $codeStep->setDeployment( $deployment );
      $codeStep->setSequence( 0 );
      $codeStep->setTitle( "Update Code" );
      $codeStep->setDetails( "Update codebase per the plan's specifications" );
      $codeStep->setDeploymentStepType(
          $em->getRepository('MyBundle:DeploymentStepType')->findOneBy(
              array( 'name' => DeploymentStepType::TYPE_OTHER )
          )
      );
      $deploymentStatusLog = new DeploymentStatusLog();
      $deploymentStatusLog->setDeployment( $deployment );
      $deploymentStatusLog->setUser( $sessionUser );
      $deploymentStatusLog->setNotes( 'New Deployment Created' );
      $deploymentStatusLog->setDeploymentStatus(
          $em->getRepository('MyBundle:DeploymentStatus')->findOneBy(
              array( 'title' => DeploymentStatus::STATUS_NEW )
          )
      );
      $deployment->addDeploymentStep( $codeStep );
      $deployment->addDeploymentStatusLog( $deploymentStatusLog );
      try {
        $em->persist( $deployment );
           $em->persist( $codeStep );
           $em->persist( $deploymentStatusLog );
        $em->flush();
        return $this->redirectSuccess(
            'Deployment created.'
          , $release->getRouteName()
          , $release->getRouteParameters()
        );
      }
      catch ( Exception $e )
      {
        $this->setFlashErrorMessage( 'Error saving deployment.' );
      }
    }
  }
  return array(
      'release' => $release
    , 'form'    => $form->createView()
  );
}

我也有同样的问题,就我而言,这是因为我正在做一个实体remove&amp;flushpostRemove生命周期事件中。从我可以在单位工程逻辑中掌握的东西,您不能在那个事件中调用Flush。这样做将冲洗所有仍在悬而未决的动作,从第一次打电话给Flush,这将被事件的冲洗电话删除。弄清楚了这一点之后,我能够找到证实我的怀疑的学说手册的这一部分:

http://docs.doctrine-project.org/en/latest/reference/events.html#postupdate-postremove-postpersist

您可以正确地假设单独冲洗每个步骤是一种不好的方法,但是如果您不使用生命周期事件,那么我不确定是什么会导致您的特定问题。我能够通过在UnitOfWork.phpexecuteDeletions函数中记录对象ID变量($oid)来调试问题。我注意到反复删除了同一ID,一旦从$this->entityIdentifiers不设置,它将在随后的删除中失败。

我的解决方案是简单地在postRemove事件中分类每个ID,然后实际上删除postFlush事件中的实体,这不是生命周期事件,因此可以进行后续的持久操作:

http://docs.doctrine-project.org/en/latest/reference/events.html#lifecycle-ext

我确定您已经继续前进,但是如果其他人遇到这个问题...

这不是"解决方案",但我希望它为他人提供更多的故障排除。

我在遵循学说的批处理质量插入件的建议时也遇到了同样的错误。仅供参考,这是来自控制器(不是像其他答案那样的生命周期事件)。

学说的推荐方法

$batchSize = 20;
for ($i = 1; $i <= 10000; ++$i) {
    $user = new CmsUser;
    $user->setStatus('user');
    $user->setUsername('user' . $i);
    $user->setName('Mr.Smith-' . $i);
    $em->persist($user);
    if (($i % $batchSize) === 0) {
        $em->flush();
        $em->clear(); // Detaches all objects from Doctrine!
    }
}
$em->flush(); //Persist objects that did not make up an entire batch
$em->clear();

当我使用与上面推荐的代码类似的东西时,它会在2000年插入大约2000插入后出现相同的错误。

更改持久的顺序

我坚持10,000个实体的顺序没有区别。如果我坚持,冲洗和清除每个循环(不是理想的,但我尝试过),那没有什么区别。

删除清除

如果我只是在$ batchsize支票中评论了$em->clear(),并且只在循环完成后才清楚地表明它,那么它就计时了:

Fatal error: Maximum execution time of 30 seconds exceeded in /var/www/core/cms/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php on line 541

所以我在脚本上放了一个 set_time_limit(3600)以防止时间,但它不再给出错误,但它耗尽了记忆:p

这表明当$em->clear()在循环中执行时,问题发生。这与其他问题一致。不幸的是,如果没有$em->clear(),您会很快用光记忆。

禁用事件听众

其他答案提到事件听众可能导致了这一点,所以我像建议的那样禁用了他们:

foreach ($em->getEventManager()->getListeners() as $event => $listeners) {
    foreach ($listeners as $listener) {
        $em->getEventManager()->removeEventListener($event, $listener);
    }
}

但这也不起作用...尽管似乎这可能是问题,但实际上并没有成功地禁用它们。

验证模式

我还验证了我的模式:

php app/console doctrine:schema:validate

,没有报告任何错误。

[Mapping]  OK - The mapping files are correct.
[Database] OK - The database schema is in sync with the mapping files.

相关内容

  • 没有找到相关文章

最新更新