web-dev-qa-db-ja.com

Doctrine-リレーションシップを通じて新しいエンティティが見つかりました

2週間以来、新しい要素をフラッシュしようとしてこの問題が発生しています。

クリティカル:Doctrine\ORM\ORMInvalidArgumentException:

エンティティの永続操作をカスケードするように構成されていない関係 'Comment#capture'を通じて新しいエンティティが見つかりました

しかし、captureはすでにデータベースにあり、findOneByで取得しているため、カスケード永続化または永続化すると、

テーブル制約違反:エントリが重複しています。

コメントは、異なるキャプチャを使用してループで作成され、新しいフィールドが設定され、すべての必須フィールドが設定されます。

すべてのエンティティが永続化および/またはfindOne(およびすべて有効)によって取得されると、フラッシュは依然として失敗します。

私はしばらくの間この問題に取り組んでいますので、助けてください

65
isundil

私は同じ問題を抱えていましたが、同じEntityManagerでした。 ManyToOneに関連するオブジェクトを挿入したかった。 cascadepersistは必要ありません。

例:

$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();
54
Mirza Selimovic

私の場合、早すぎる電話

$this->entityManager->clear();

問題を引き起こしました。また、次のように最近のオブジェクトをクリアするだけで消えました

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

私の答えはトピックに関連していますが、あなたの特定のケースにはあまり関連していませんので、上記の答えは私を助けなかったので、グーグルの人にはこれを投稿します。

私の場合、リレーションを持つバッチ処理エンティティで同じエラーが発生し、そのリレーションはまったく同じエンティティに設定されていました。

私がDID間違っている:

エンティティのバッチを処理しているときに$this->entityManager->clear();を実行すると、次のエンティティのバッチが切り離された関連エンティティを指すため、このエラーが発生します。

間違ったこと:

  1. $this->entityManager->clear();$this->entityManager->detach($entity);と同じように機能することは知りませんでしたが、リポジトリのすべてのエンティティを切り離すだけです。

  2. $this->entityManager->clear();も関連するエンティティを切り離すと思いました。

何をすべきか:

エンティティを反復処理し、それらを1つずつデタッチする必要があります。これにより、将来のエンティティが指している関連エンティティがデタッチされません。

これが誰かの助けになることを願っています。

29
drakonli

まず第一に、あなたはあなたのコードにもっと注意を払う必要があります、あなたのエンティティとコントローラに3つの異なるインデントのように見えます-これは読みにくく、 Symfony2コーディング標準 に適合しません。

コントローラのコード 表示 は完全ではありません。$this->activeCaptureがどこから来るのかわかりません。あなたの中には、Captureオブジェクトを含む$people['capture']があります。これはとても重要です。

$people['capture']のキャプチャが$this->entityManager(別のEntityManagerから)(これがどこから来たのかわかりません)から永続化/フェッチされた場合、Doctrine2はオブジェクトが既に永続化されていることを知りません。

これらのすべての操作に対してDoctrine Entity Managerの同じインスタンスを使用するようにしてください(EMオブジェクトでspl_object_hashを使用して、それらが同じインスタンスであることを確認してください)。

EntityManagerにCaptureオブジェクトの処理方法を伝えることもできます。

// 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);

これで解決しない場合は、より多くのコードを提供する必要があります。

9
Damien

エラー:エンティティの永続操作をカスケードするように構成されていない「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;
6
Roberto

問題のエンティティを更新すると、私の場合に役立ちました。

/* $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にはすでにProductが他の場所に設定されているにもかかわらず(differentEntityManagerのインスタンスを介して設定されていることがわかります)、まだエラーが発生していました。

したがって、これは既存の製品のidを取得してから、その参照を取得し、setProductを使用して接続を「更新」するという、一種のハックです。後で、コードにEntityManagerのインスタンスを1つだけ持つようにして、修正しました。

2
Dennis

add new entityを実行しようとしたときにもこのエラーが発生しました。

A new entity was found through the relationship 'Application\Entity\User#chats' 
that was not configured to cascade persist operations for entity: ###. 
To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or
configure cascade persist  this association in the mapping for example @ManyToOne(..,cascade={"persist"}).

私の場合は、保存すべきではないエンティティを保存しようとしました。エンティティの関係が満たされ、保存しようとしました(UserはMany2Manyに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();
0
shukshin.ivan