2012-02-02 14 views
6

私は3つのDoctrineエンティティを持っています:デバイスはDevice \ StatusとOneToOneの関係を持ち、Device \ Status \ BatteryとOneToOneの関係にあります。Doctrine 2マルチレベルOneToOneカスケード

関連するエンティティと、私が読んだものの間に{cascade = "persist"}を設定しました。Doctrineが自分で何もしなくてもそれぞれのエンティティを自動的に保持するために必要ですコード。ここで

は私がに問題あるんだよ:このコードを実行した後

$device = new \Entities\Device(); 
$device->setId(100); 

$status = $device->getStatus(); 
$status->setIpAddress('192.168.0.1'); 

$battery = $status->getBattery(); 
$battery->setInternalLevel(60); 

$em->persist($device); 
$em->flush(); 

を、私は次のエラーを取得する:

Entity of type Device\Status\Battery has identity through a foreign entity 
Device\Status, however this entity has no identity itself. You have to call 
EntityManager#persist() on the related entity and make sure that an identifier 
was generated before trying to persist 'Device\Status\Battery'. In case of 
Post Insert ID Generation (such as MySQL Auto-Increment or PostgreSQL SERIAL) 
this means you have to call EntityManager#flush() between both persist 
operations. 

私の質問は:セットアップへの正しい方法は、私のものですエンティティが正しい順序で永続化されていることを確認しますか?

エンティティのためのコードはここで見つけることができます:https://gist.github.com/1753524

すべてのテストは、教義2.2サンドボックスを使用して行われてきました。

+0

私はほとんど同じ問題を抱えていました。 Uはそれぞれの持続の間にフラッシュする必要があります。 – CappY

+0

@CappY Doctrineの文書によると、{cascade = "persist"}が各エンティティに設定されているので、各エンティティを手動で永続化する必要はありません。このコード*はそのまま動作するはずです。 http://readthedocs.org/docs/doctrine-orm/en/latest/reference/working-with-associations.html#transitive-persistence-cascade-operations – Taeram

+0

[短い、自己完結型の、正しい例](http ://sscce.org/)。あなたのコードは 'protected 'プロパティに直接値を代入しようとすると、アクセス違反を引き起こします。' $ device-> id = 100' – Phil

答えて

6

@CappYが正しいと思います。

問題はステータスエンティティにあります。 getBattery()を実行して新しいBatteryインスタンスを作成すると、これはgetBattery()という名前のStatusインスタンスに関連しています。

このインスタンスはまだデータベースに格納されていないため、IDは生成されていません(@GeneratedValueと注釈が付けられているため)。あなたはカスケード持続についてほぼ正しいです。それ以外はのメモリにを実行しました。

は、getBattery()を実行する前にステータスエンティティを永続化してフラッシュし、そのエンティティをバッテリでIDとして使用する必要がある場合に必要です。そうでない場合は、単純にBatteryのidフィールドを追加することができます。

+0

私は実際にあなたの答えを受け入れるだけではなく、賞金を獲得するために実際に "+50"ボタンを押していなければならないことに気付きました。だからそこに行く:) – Taeram

+0

ありがとうたくさん:) – jere

0

リレーションマッピングにcascade = {"persist"}を追加する必要があります。正解として選択した答えも正しいですが、その解決策では、親データを挿入した後に何か問題が生じた場合、トランザクションのロールバックはありません。 autocommit = falseを設定し、トランザクションを手動でコミットする必要があります。カスケード= {"persist"}では、あなたはしないでください。データベース操作中に何かが間違っていると、すべてがロールバックされます。

+0

それは彼がやっていたもので、それは動作しませんでした。あなたは完全な例を提供できますか? – cheesemacfly

関連する問題