Doctrine 2删除实体问题

时间:2011-05-06 14:12:04

标签: php doctrine-orm

当我使用实体管理器删除实体时,我遇到了一个奇怪的错误。正在抛出一个异常,说“通过未配置为级联持久化操作的关系找到新实体”但我没有新实体。我认为这可能是Doctrine中的一个错误,但我想先问一下,确保在填写报告之前我没有做错任何事。

相关代码:

<?php
$em = Doctrine\ORM\EntityManager::create(array('driver' => 'pdo_sqlite', 'memory' => true), $config);

$qb = $em
    ->getRepository('Bar')
    ->createQueryBuilder('bar1')
    ->select('bar1, foo1, bar2')
    ->join('bar1.foo', 'foo1')
    ->join('foo1.bar', 'bar2')
;

$qb->getQuery()->getResult();

$bar = $em->getRepository('Bar')->findOneBy(array('id' => 20));

$em->transactional(function($em) use ($bar) {
    $em->remove($bar);
    $em->flush();
});

如果删除包装删除和刷新操作的$em->transactional,则删除有效。此外,如果我删除前一个查询的$qb->getQuery()->getResult();,则删除和刷新呼叫将起作用。

我得到的错误是:

Fatal error: Uncaught exception 'InvalidArgumentException' with message 'A new entity was found through a relationship that was not configured to cascade persist operations: Bar@0000000049dcca970000000025d8d6f9. Explicitly persist the new entity or configure cascading persist operations on the relationship.' in doctrine2-orm/lib/Doctrine/ORM/UnitOfWork.php:576
Stack trace:
  #0 doctrine2-orm/lib/Doctrine/ORM/UnitOfWork.php(495): Doctrine\ORM\UnitOfWork >computeAssociationChanges(Array, Object(Doctrine\ORM\PersistentCollection))
  #1 doctrine2-orm/lib/Doctrine/ORM/UnitOfWork.php(537): Doctrine\ORM\UnitOfWork->computeChangeSet(Object(Doctrine\ORM\Mapping\ClassMetadata), Object(Foo))
  #2 doctrine2-orm/lib/Doctrine/ORM/UnitOfWork.php(256): Doctrine\ORM\UnitOfWork->computeChangeSets()
  #3 doctrine2-orm/lib/Doctrine/ORM/EntityManager.php(334): Doctrine\ORM\UnitO in doctrine2-orm/lib/Doctrine/ORM/UnitOfWork.php on line 576

可在此gist中找到完整的工作示例。

2 个答案:

答案 0 :(得分:4)

我在填写bug report之后最终想到了这一点。

transactional在内部执行刷新,双重刷新正在创建此问题。我不认为双重冲洗会破坏事情,但我并不认为这一点。

据说我没有正确使用transactional,Doctrine 2有隐式事务,除了非常具体的实例外,不需要在transactional中包装数据库调用。

来自Doctrine 2文档

  

如果要在工作单元中包含自定义DBAL操作,或者想要使用需要活动事务的EntityManager API的某些方法,则需要显式事务划分。此类方法将抛出TransactionRequiredException以通知您该需求。

答案 1 :(得分:2)

transactional()用于刷新操作。 flush已多次重做