2014-01-05 33 views
2

我正在研究一個包含Doctrine和傳統內聯SQL混合使用的數據庫訪問的Web項目。隨着時間的推移,我們正在從後者遷移到前者。無效的Doctrine實體被創建

其中一個數據庫表(表A)有一個非正式的外鍵(即在SQL表定義中沒有實際的約束)列。此列中的值可以爲空,但有時此列中的值引用另一個表(表B)主鍵,此鍵已被刪除。

表A與表B的關係在表A的Doctrine中的實體定義中形式化。當我從表A中的現有行創建實體的實例,並且非正式外鍵列的值不再位於表B中時,那麼它似乎創建了無效的表B實體。即對象被設置,並且我可以通過我們創作的TableB-> getId()方法來查詢它的id,但是任何其他TableB-> getProperty()都會失敗並引發錯誤。

由於我已經在處理歷史數據,因此我需要一個運行時解決方案。我需要通過檢查來確定表B實體是否有效。 我可以把它放在try-catch循環中,但這不是我們代碼庫中的常見模式,並且看起來不太優雅。 是否有一個規範的方法來檢查一個Doctrine實體的有效性來解決這個問題?

謝謝

+0

我的意見是,你正在尋找框架級別的解決方案,而實際的問題是在數據庫/模型級別。我寧願專注於創建清晰的數據模型,以更好地表現業務需求/現實,並使用數據庫工具(僅返回「有效」數據的視圖,同步數據的觸發器等)實現兼容性。然後完成並且工作可靠,丟棄舊模型並使用新模型。否則,如果系統中充滿了補丁和黑客,並且每次下一次更改都會導致越來越多的努力,那麼您最終可能會得到這樣的結果。 – a1ex07

+0

同意,並且將是一個更長期的解決方案,但最後期限... – JonRed

回答

1

正如我所看到的,有兩件事情你應該做。

首先修復您的數據損壞,這是必須的。如果A指向一個不存在的B,那麼A就不應該指向任何東西。 SELECT a.id FROM table_a a LEFT JOIN table_b b ON b.id = a.table_b_id WHERE b.id IS NULL。此查詢將選擇所有不再存在的FK,您可以簡單地使用該列表將a.table_b_id更新爲NULL。

其次,你應該(不要在你的getter中)處理代碼中的關係問題。我不確定是否教條拋出EntityNotFoundException或僅與find($pk)這樣做,但我相信你可以檢查你的獲得者的返回是null還是捕獲該異常。

+0

我們可以修復歷史數據,但UI仍然允許用戶進入此狀態。我們會解決這個問題,但不是在這個衝刺中。這裏的原則表現得非常奇怪 - 即使是一個存儲庫 - > find(pk)命令也會返回這個無效的對象。無論如何,我確實選擇使用EntityNotFoundException來嘗試使用try-catch。無論如何感謝您的幫助 - 真的很感激。 – JonRed

+0

我在數據腐敗等固定類似的情況。然而,修復數據損壞,將使它不可能發生,因爲它不會檢索對象的第一個地方作爲關係「不存在」從A到B;)我不知道這有多少桌子,但在幾張桌子上這樣的修復不應超過30分鐘。從開發者視角來看,修復這種腐敗會「自動修正」主義問題,因此花費你的時間減少^。^ –

+0

是的,但是讓你處於這種狀態的現有UI並不是Doctrine,所以在這之前修正了數據可能會被正常使用損壞。歷史數據修復很容易;使用內聯SQL翻譯舊的Backbone和一個1000行的PHP頁面並非如此。 – JonRed