假设我有两个实体News
和Tag
。他们有一对多的关系。
此外,我对标签表('news_id', 'name')
有一个唯一约束。
现在我现在的状态是:
tags
---------------------
id | news_id | tag
---------------------
1 | 1 | world
2 | 1 | event
如果我这样做:
$em->remove($tag2);
$em->persist(new Tag($tag2->getNews(), 'event'));
我得到Integrity constraint violation: 1062 Duplicate entry
,因为在删除旧实体之前,学说会尝试插入。当我更新/删除时也会发生同样的情况。是否有可能告诉学说先删除旧实体?或者有更好的解决方案吗?
另一个例子:
一个简单的表格:
tags
---------------------
id | tag
---------------------
1 | world
2 | event
为tag
列设置了UNIQUE约束。
现在我做了:
$tags = $em->getRepository('Tag')->findAll();
$tempName = $tags[0]->getName();
$tags[0]->setName($tags[1]->getName());
$tags[1]->setName($tempName);
并获得相同的错误,因为它尝试使用'event'值更新第一个标记,并且已经有重复。
PS:我知道我可以拨打flush
两次,但这不是一个好主意。
答案 0 :(得分:0)
我自己也遇到了这个问题,一直试图了解原因和方法。
PS:我知道我可以两次拨打同花,但这不是一个好主意。
如果您尝试在单个交易中安全地执行所有DML查询,那只是一个坏主意。
Doctrine将按以下顺序提交DML语句:
我怀疑这种排序背后的目标是满足FK约束。即如果删除实体,则需要先删除对它的所有引用。
如果您需要按特定顺序执行DML查询,我相信您应该使用事务,如Transactions and Concurrency中的Doctrine文档中所述。
因此,使用此方法,您可以两次调用flush()
,但是您可以在单个事务中执行此操作。以下是基于您的标记的示例,假设标记名称是唯一的。
<?php
$em->beginTransaction();
try {
$tag2 = $em->find(2);
$tagName = $tag2->getName();
$newTagWithSameName = new Tag($tagName);
$em->remove($tag2);
$em->flush();
$em->persist($newTagWithSameName);
$em->flush();
$em->commit();
} catch (Exception $e) {
$em->rollback();
throw $e;
}