2011-08-31 120 views
7

我使用Doctrine 2作爲我的ORM,事情進展順利,但我一直想知道EntityManager#persist()方法。該"Persisting entities"文件說,下面即將persist()呼籲對象X知道什麼時候調用persist

如果X是一個已經存在的管理實體,它是由持續經營忽略。

這使我相信persist()只需要在對象是新的並且尚未保存到數據庫時調用。然而,對於"Deferred Explicit" change tracking policy的文件說:

...學說2只通過對EntityManager的呼叫#堅持(實體)認爲,已明確標記爲變化檢測實體...

...聽起來像persist()必須在對象上調用它才能被更新。什麼時候應該叫persist()?如果只使用新對象,無論何時更新實體,是否有重要的性能影響,並讓教條理清差異?

回答

8

對於Deferred Explicit policy(這不是默認策略),您需要在每個修改後的實體上顯式調用persist()以使其保留原則。 (除級聯持久性關聯外)。

主義仍然需要將每個屬性的新值與原始值進行比較,以瞭解更新哪個屬性,因此如果您的實體過多,這可能會導致性能下降。

使用default change tracking policy您只需要調用堅持尚未由Doctrine管理的實體(使用new創建的實體)。有了這個策略,當你調用flush()時,doctrine會自動檢測哪些實體已經更新並且需要被持久化。

+0

請注意,當使用延遲隱式更改跟蹤(默認值)時,Doctrine會將每個屬性的原始值與每個屬性的新值(對於UnitOfWork中的每個實體,與延遲顯式相同)進行比較,而不僅僅是你稱之爲'堅持()'的那個。 –

+3

生活了一半,直到問題激起思想,默認政策是延期顯性政策。 –

6

該文檔有些誤導。在隱式跟蹤模式下,所有實體都有一個狀態(管理,刪除,分離等)。通過find()和類似方法獲得的實體(基本上所有不是用new創建的)都已處於受管理狀態。在flush()上,檢查所有託管(和刪除)實體的更改,並在必要時更新數據庫。

在顯式跟蹤模式下,還有一個額外的髒檢查列表,persist()將該對象(以及可能的關聯對象,取決於級聯設置)添加到該列表中。只有骯髒的檢查清單上的項目才被考慮更新。沖洗後清除髒檢查列表,因此如果您再次刷新並再次更改同一個對象,則必須再次調用persist()。 (相反,管理狀態在沖洗後保留。)

您可以在Doctrine\ORM\UnitOfWork類中查看自己的詳細信息;搜索isChangeTrackingDeferredImplicit/isChangeTrackingDeferredExplicit(在這兩種政策下,這些是行爲不同的唯一地方)。

+0

我有一個分離的實體(通道)來形成緩存結果集,我需要添加數據隻影響數據表。有沒有辦法在不合並分離頻道的情況下堅持頻道的數據? – andig

+0

@andig,不確定。我認爲你是在談論[這個問題](http://stackoverflow.com/questions/18102728/doctrine-persisting-detached-entities) - 當你真的想要添加時,爲什麼你需要堅持頻道?一個新的數據實體? – Tgr

+0

優秀的問題。我正在使用遺留代碼,並且對於Doctrine還是新手。將調查如何/如果我可以直接持久化數據的ArrayCollection。如果工作,我會很感激交叉答案,所以我可以投票。 – andig

相關問題