2017-09-26 3 views
4

私はZF3アプリケーションのDBALをDoctrineに移行しており、ステップバイステップで進めたいと考えています。現在、私はMapperオブジェクトの階層を使用しています。同様のFooEntity階層の各エンティティは、FooMapperに従います。ネストされたエンティティの保存は、ネストされたMapperによって実行されます。 は、Zend\Db\Sql\InsertまたはZend\Db\Sql\Updateというエンティティを保存し、BarMapperBarEntity)などのサブエンティティに適切なMapperを呼び出します。私はcascade={"persist"}ようにDoctrineの便利な機能を開始する前にDoctrineでエンティティ階層の最初のレベルのみをペリストにする方法はありますか?

今、私はMapperの階層を維持するために、ちょうどpersist(...) & flush()でネストされた実体のトップレベルの保存を実行したいです。

しかし、私は

public function save(AbstractDataObject $dataObject) 
{ 
    $newLogicalConnection = $this->logicalConnectionMapper->save($dataObject->getLogicalConnection()); 
    $newUser = $this->userMapper->save($dataObject->getUser()); 

    $dataObject->setLogicalConnection($this->entityManager->find(LogicalConnection::class, $newLogicalConnection->getId())); 
    $dataObject->setUser($this->entityManager->find(User::class, $newUser->getId())); 

    $this->entityManager->persist($dataObject); 
    $this->entityManager->flush(); 

    return $dataObject; 
} 

それをしようとすると、私はそうはエラー

A new entity was found through the relationship 'MyNamespace\DataObject\AbstractEndpoint#externalServer' that was not configured to cascade persist operations for entity: MyNamespace\DataObject\[email protected] 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"}). If you cannot find out which entity causes the problem implement 'MyNamespace\DataObject\ExternalServer#__toString()' to get a clue. 

を取得し、Doctrineはそのサブエンティティとエンティティ全体を保存しようとするようで、この試みは、のいずれかに障害が発生しましたより低いレベル。しかし、なぜ?私はcascadeオプションを有効にしておらず、Doctrineが最上位レベルだけを保存することを期待しています。

なぜDoctrineはトップレベルだけでなくエンティティ全体を保存しようとしますか?そして、それをどのようにして与えられたエンティティのトップレベルだけを保存するか?

+0

私は方法がないと思います。新しいエンティティエラーメッセージは基本的に、カスケードを有効にする必要があるという警告です。 2つのオブジェクトの間に関係があることを考えれば、Doctrineはそれを維持しようとします。もちろん、関係マッピングを削除することはできます。 – Cerad

+0

@Ceradご意見ありがとうございます。たぶん、私は 'cascade = {" persist "}'の意味が間違っていると理解しています。私の期待は、 'cascade = {" persist "}'アノテーションで関連するオブジェクトが保存され、保存されないということでした。しかし、カスケードセービングが 'cascade = {" persist "}"なしでも動作する場合、このアノテーションの意味は何ですか? – automatix

+0

再び警告です。いくつかの人々は明示的にすべての子エンティティを維持したい場合、カスケードは必要なく、警告は消えてしまいます。 Doctrine ORMについての一般的なことの1つは、それが特定の方法で物事を行うということだけです。あなたはそれと一緒に暮らすか、それを使用しません。個人的には、私が既に働いているdbalベースのシステムを持っていれば、それに固執します。 – Cerad

答えて

1

あなたはAbstractEndpoint->externalServerに新しいエンティティ(まだ永続化されません)を持っており、このフィールドは、言い換えればcascade={"persist"}

として注釈されていないため、このエラーを取得し、あなたが新しいエンティティExternalServerを先ほど作成して、それを持続していませんでしたそしてcascade={"persist"}

として注釈されていないAbstractEndpoint->externalServerエンティティとの関係として、これを追加しましたので、教義は、この新しいエンティティを持ってしまい、それをどうするかわかりません。データを失わないために、この例外が発生します。

  1. あなたはcascade={"persist"}ExternalServerエンティティ
  2. 注釈AbstractEndpoint->externalServerを作成した直後$this->entityManager->persist($externalServer);を追加:あなたは二つのことを行うことができます。この問題を解決するには

    。トップレベルのエンティティだけをDBに保存して、手動で永続化する必要があるか、または追加しないでください。

そして今、あなたの質問に答える:

をしかし、なぜ?私はカスケードオプションを有効にしておらず、トップレベルだけを保存することをDoctrineに期待しています。

どういうわけか、あなたのオブジェクトモデルでの関係を介してDoctrineはExternalServerエンティティに移動し、それをunpersisted状態で見つけます。リレーショナルデータベースに存在しないレコードへのリンクを持つオブジェクト階層の最上位レベルのみを保存することはできません。あなたがDoctrineにあなたのためにそれをやりたくない場合は、あなた自身でこの状況を処理しなければならない、または関係から永続的なエンティティを削除する必要があります

関連する問題