2012-02-02 111 views
6

我有三個Doctrine實體:Device,它與Device \ Status具有OneToOne關係,而Device \ Status與Device \ Status \ Battery具有OneToOne關係。Doctrine 2多級OneToOne級聯

我在相關實體之間設置了{cascade =「persist」},並且從我所讀到的內容來看,這應該是所有爲自動堅持每個實體所需的全部內容,而無需自己做任何事情代碼。

這裏是我有什麼用的問題:

$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. 

我的問題是:什麼是正確的方法來設置我的實體以確保它們保持正確的順序?

爲實體的代碼可以在這裏找到:使用學說2.2沙箱已經進行https://gist.github.com/1753524

所有測試。

+0

我有幾乎相同的問題。你必須在每次持續之間調用flush。 – CappY 2012-02-05 18:03:11

+0

@CappY根據Doctrine文檔,因爲我爲每個實體設置了{cascade =「persist」},所以我不需要手動持久化每個實體。此代碼*應該*按原樣工作。 http://readthedocs.org/docs/doctrine-orm/en/latest/reference/working-with-associations.html#transitive-persistence-cascade-operations – Taeram 2012-02-06 04:10:21

+0

請提供一個[簡短,自包含,正確的示例](http ://sscce.org/)。當你嘗試將值直接賦值給'protected'屬性時,你的代碼觸發訪問衝突,即'$ device-> id = 100' – Phil 2012-02-06 05:08:00

回答

6

我認爲@CappY是對的。

問題出在狀態實體中。當您執行getBattery()並創建一個新的Battery實例時,它與您調用getBattery()的Status實例相關。

由於該實例尚未存儲在數據庫中,因此尚未生成id(因爲它的註釋爲@GeneratedValue)。你對cascade persist幾乎是正確的。除了它在內存中執行

所以你需要堅持和刷新狀態實體之前做getBattery()如果你想使用該實體作爲電池中的id。否則你可以簡單地爲電池添加一個ID字段:)

+0

我剛剛意識到我實際上不得不按下「+50」按鈕來獎勵賞金,而不只是接受你的答案。所以你去:) – Taeram 2012-02-10 02:12:14

+0

非常感謝:) – jere 2012-02-10 11:24:25

0

你必須在你的關係映射中添加cascade = {「persist」}。您選擇的正確答案也是正確的,但是通過該解決方案,如果在插入父數據後出現任何錯誤,則不會有事務回滾。您必須設置autocommit = false並手動執行提交事務。級聯= {「堅持」}你不必。在數據庫操作過程中出現任何錯誤,所有內容都將被回滾。

+0

這就是他正在做的,它沒有奏效。你能提供一個完整的例子嗎? – cheesemacfly 2013-04-08 19:31:50