2
在我的应用程序有一个具有自参考ManyToOne
协会(很多孩子可以指向一个单亲)的实体。而且我有一个功能,可以一次使用Doctrine ORM对许多实体进行批量更新。为了防止由于许多实体在更新后加载实体而使性能显着下降。
问题:
当我detach
有孩子后来尝试更新任何这些孩子主义抱怨说,它不知道父了的实体。即使我试图更新子之前merge
父母实体。
问:
我在做什么错了,当我拆开父实体?我试过在父列上执行级联=“合并”和/或“分离”,并且当我尝试坚持时,Doctrine仍然抱怨父母是未知实体。
我嘲笑一个简单的例子,再现这一点。见下文。
测试代码:
实体\ Thing.php
/**
* @ORM\Entity()
* @ORM\Table(name="things")
*/
class Thing
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\ManyToOne(targetEntity="Thing", inversedBy="children", cascade={"detach","merge"})
* @ORM\JoinColumn(name="parentId", referencedColumnName="id", onDelete="SET NULL")
*/
protected $parent;
/**
* @ORM\OneToMany(targetEntity="Thing", mappedBy="parent")
*/
protected $children;
/**
* @ORM\Column(type="string", length=64)
*/
protected $name;
public function __construct($name = null)
{
$this->children = new ArrayCollection();
$this->name = $name;
}
// .. SNIP ...
}
测试行动:
public function testThingAction($_route)
{
$em = $this->getDoctrine()->getEntityManager();
$repo = $em->getRepository('AcmeThingBundle:Thing');
// simple setup of a couple things in the DB
$t1 = $repo->findByName('Thing1');
if (!$t1) {
$t1 = new Thing('Thing1');
$t2 = new Thing('Thing2');
$t2->setParent($t1);
$em->persist($t1);
$em->persist($t2);
$em->flush();
return $this->redirect($this->generateUrl($_route));
}
list($t1, $t2) = $repo->findAll();
// detach and re-merge Thing1
// This should cause Thing1 to be removed and then re-added
// to the doctrine's known entities; but it doesn't!?
$em->detach($t1);
$em->merge($t1);
// try to update T2
$t2->setName('Thing2 - ' . time());
$em->persist($t2);
// will fail with:
// A new entity was found through the relationship Thing#parent
$em->flush();
return array();
}
你说'合并'返回一个新对象(通常我不需要重新合并实体;我只是在我的测试中这样做)。不过,我认为这是教义上的一个潜在缺陷。因为一旦我将父母分开,我不能再对任何孩子坚持任何改变。任何人都有任何见解,为什么这是预期的行为? – lifo 2013-02-13 15:15:38
我不会把它称为教义上的缺陷。你要求它将一个孩子坚持到一个它不知道的父母那里。就教条而言,这样做会违反表中的外键约束(因为它不能确认实体是否有效)。我认为还有其他的优化你应该担心,而不是分离所有这些实体。例如,像显式地将要保存的实体传递给'flush()'方法,所以教义不会扫描它们。 – 2013-02-13 15:35:48
那么,这是有道理的,并让我意识到,我正在关注错误的实体重新合并。我可以合并可以级联到父级的'$ t2',而不是试图合并'$ t1'。我已经证实了这个作品。感谢您的意见。我并没有真正使用很多级联,并且我尝试了其他优化的所有方式,但是分离是我发现使导入功能不起作用而不减速到每秒1次或甚至更慢的唯一方式。 – lifo 2013-02-13 15:51:47