Symfony 条令-通过关系找到一个新实体

Symfony 条令-通过关系找到一个新实体,symfony,doctrine,Symfony,Doctrine,自2周以来,我们在尝试刷新新元素时遇到了以下问题: 关键:条令\ORM\orInvalidargumentException: 通过关系“Comment#capture”找到了一个新实体,该关系未配置为级联实体的持久化操作 但是capture已经在数据库中,我们通过findOneBy获取它,所以如果我们级联持久化它,或者持久化它,我们会得到一个 表约束冲突:重复条目 注释是在一个循环中创建的,其中包含不同的捕获,并设置了一个新的、所有必需的字段 当所有实体都被保存和/或通过findOne(且所有

自2周以来,我们在尝试刷新新元素时遇到了以下问题:

关键:条令\ORM\orInvalidargumentException:

通过关系“Comment#capture”找到了一个新实体,该关系未配置为级联实体的持久化操作

但是
capture
已经在数据库中,我们通过
findOneBy
获取它,所以如果我们级联持久化它,或者持久化它,我们会得到一个

表约束冲突:重复条目

注释是在一个循环中创建的,其中包含不同的捕获,并设置了一个新的、所有必需的字段

当所有实体都被保存和/或通过
findOne
(且所有实体都有效)获取时,刷新仍然失败


我讨论这个问题已经有一段时间了,所以请帮助我首先,您应该更好地保护您的代码,我在您的实体和控制器中看到了3个不同的缩进-这很难阅读,并且不符合要求

您控制器的代码不完整,我们不知道从哪里来
$this->activeCapture
。里面有一个
$people['capture']
,我猜它包含一个
capture
对象。这是非常重要的

如果
$people['Capture']
中的捕获是从另一个EntityManager(而不是
$this->EntityManager
(我们同样不知道它来自何处)持久化/获取的,Doctrine2就不知道该对象已经持久化了

您应该确保对所有这些操作使用同一实例的条令实体管理器(在EM对象上使用
spl\u object\u hash
,以确保它们是相同的实例)

您还可以告诉EntityManager如何处理捕获对象

// Refreshes the persistent state of an entity from the database
$this->entityManager->refresh($captureEntity);

// Or
// Merges the state of a detached entity into the 
// persistence context of this EntityManager and returns the managed copy of the entity.
$captureEntity = $this->entityManager->merge($captureEntity);
如果这没有帮助,您应该提供更多代码。

错误: “Comment#capture”未配置为级联实体的持久化操作

问题是:

/**
 * @ORM\ManyToOne(targetEntity="Capture", inversedBy="comments")
 * @ORM\JoinColumn(name="capture_id", referencedColumnName="id",nullable=true)
 */
 protected $capture;
不要配置级联持久化

试试这个:

/**
 * @ORM\ManyToOne(targetEntity="Capture", inversedBy="comments", cascade={"persist", "remove" })
 * @ORM\JoinColumn(name="capture_id", referencedColumnName="id",nullable=true)
 */
 protected $capture;

就我而言,这是一个过早的决定

$this->entityManager->clear();
造成问题的原因。它也消失了,只做了一个明确的最近的对象,如

$this->entityManager->clear($capture);

我遇到了同样的问题,它是相同的
EntityManager
。我想插入一个与对象相关的
ManyToOne
。我不想要一个
级联
持久化

例如:

$category = $em->find("Category", 10);

$product = new Product();
$product->setCategory($category)

$em->persist($product);
$em->flush();
这对我来说也是一个例外

因此,解决方案是:

$category = $em->find("Category", 10);

$product = new Product();
$product->setCategory($category)

$em->merge($product);
$em->flush();

我在尝试添加新实体时也遇到了此错误

我的情况是,我试图保存实体,但不应该保存。实体关系已填充并试图保存(
User
has
Chat
在许多情况下,但Chat是临时实体),但存在一些冲突

所以,如果我使用
cascade={“persist”}
我会得到不想要的行为-垃圾实体被保存。我的解决方案是从任何保存实体中删除非保存实体:

// User entity code
public function removeFromChats(Chat $c = null){
    if ($c and $this->chats->contains($c)) {
        $this->chats->removeElement($c);
    }
}
保存代码

/* some code witch $chat entity */
$chat->addUser($user);

// saving
$user->removeFromChats($chat);
$this->getEntityManager()->persist($user);
$this->getEntityManager()->flush();
我的答案与主题相关,但与您的具体情况不太相关,所以对于那些在谷歌上搜索的人,我发布了这篇文章,因为上面的答案对我没有帮助

在我的例子中,我对具有关系的批处理实体有相同的错误,并且该关系被设置为非常相同的实体

我做错了什么:

当我执行
$this->entityManager->clear()时在处理一批实体时,我会得到这个错误,因为下一批实体将指向分离的相关实体

出了什么问题:

  • 我不知道
    $this->entityManager->clear()的工作原理与
    $this->entityManager->detach($entity)相同仅分离所有repositorie的实体

  • 我认为
    $this->entityManager->clear()还分离相关实体

  • 我应该做什么:

    我应该迭代实体并逐个分离它们——这不会分离未来实体指向的相关实体


    我希望这对某人有所帮助。

    刷新相关实体有助于我的案例

    /* $item->getProduct() is already set */
    
    /* Add these 3 lines anyway */
    $id = $item->getProduct()->getId();            
    $reference = $this->getDoctrine()->getReference(Product::class, $id);
    $item->setProduct($reference);
    
    /* Original code as follows */
    $quote->getItems()->add($item);
    $this->getDoctrine()->persist($quote);
    $this->getDoctrine()->flush();
    
    尽管我的
    $item
    已经在别处设置了
    产品
    (结果是通过
    EntityManager
    的不同实例设置的),但我仍然收到了错误


    这是一种黑客行为,通过检索现有产品的
    id
    ,然后检索它的引用,然后使用
    setProduct
    来“刷新”连接。后来我通过确保代码中只有一个
    EntityManager
    实例来修复它。

    向我们展示一些代码,例如控制器和实体。这是一个相关问题,可能会对您有所帮助:以下是来自控制器的代码:,以下是实体注释中的字段:同时访问条令是否可能会导致此错误?我还尝试使用自定义锁定原则,但没有附加任何内容…你的粘贴箱不再存在->除非绝对必要,否则不在帖子中使用链接是一个很好的理由。我尝试刷新我拥有的所有activeCapture实体,但什么都没有。。。我确信我只有一个EntityManager,因为我使用“get('doctrine.orm.default\u entity\u manager')”。$this->activeCapture在这里给出:getActiveCapture在这里给出:为什么要分离第36行的捕获?如果捕获在某个地方被引用,Doctrine不再知道任何关于它的信息,然后可以抛出您得到的异常类型。此过程允许我们刷新捕获实体,但此函数打印日志,不调用(不打印调试),我正在尝试删除它,对于提到必须是同一实体管理器实例的检查+1,merge会导致Doctrine找到具有相同ID的现有$product(我们称之为$originalProduct),并将$product与$originalProduct合并。请注意,这样做的副作用是$
    /* $item->getProduct() is already set */
    
    /* Add these 3 lines anyway */
    $id = $item->getProduct()->getId();            
    $reference = $this->getDoctrine()->getReference(Product::class, $id);
    $item->setProduct($reference);
    
    /* Original code as follows */
    $quote->getItems()->add($item);
    $this->getDoctrine()->persist($quote);
    $this->getDoctrine()->flush();