私は「Foo」と「Bar」と呼ぶ2つの実体の間に1対多の関係を持つDoctrineアプリケーションを開発しています。 「バー」は関係の所有側であり、この文脈では奇妙に見えるかもしれない。私はfooに属するすべてのバーを順番に処理し、変更をフラッシュする必要があります。しかしながら、バーエンティティは、サイズが非常に大きい(それぞれ数メガバイト)。各fooには多くのバーが存在することがあるので、些細なループがすべてのRAMを使い果たします。関係の一部である教義の実体を分離する
foreach ($foo->getBars() as $bar) {
$bar->setSomething(...potentially large blobs...);
// ... dozens of more setters (and getters)
$em->flush();
// or: $em->flush($bar);
$em->detach($bar);
}
// unrelated code
$foo->setDoStuff(...)
$em->flush();
は、しかし、これが2回目の反復でひどく失敗何らかの理由で第二フラッシュは()が発生しますので、:すべてのバーが処理され、フラッシュ、そのようにされた後、私は紅潮し、取り外すことにより、この問題を解決しようとしていますオブジェクトグラフの最初のバーを表示し、それが永続化されていないと不満を表明します(アンマネージドです)。エラーメッセージは次のとおりです。「エンティティの永続操作をカスケードするように構成されていない関係「Foo#bars」によって新しいエンティティが見つかりました
すべてのエンティティではなく特定の$バーのみをフラッシュすると、正常に完了しますが、後で引数なしで$ em-> flush()を使用することは不可能になります。なぜなら、それらがアンマネージエンティティに遭遇するからです。
$ fooを切り離すとこれが解決されますが、後で変更してフラッシュするコードに$ fooへの参照がたくさんあるので、これは残念ながら受け入れられません。
どうすればこの問題を解決できますか? clear()/ detach()に関連するドキュメントのすべての例は、非常に自明であり、関係を伴わないようです。
理想的には、$ em-> getReference()で取得されたもののように、非水和プロキシ遅延ロード状態にオブジェクトを戻す方法があります。ガベージコレクタは、以前にすべてのフィールドで使用されていたメモリを解放します。
特定のフラッシュが他のエンティティを永続化していない場合は、カスケードを使用できますか?とにかくメモリが大きな懸念である場合は、それぞれをロードするのが最良の選択肢ではない場合は、fooのバーIDを最初にロードし、ループの各バーを別々に読み込み、設定を解除します。 – mickadoo
@mickadoo問題は、物事が洗い流されないということではありません。しかし、あなたのコメントの第二の部分は良い方向を示唆しています、私は調査します。 – jlh