2012-10-10 34 views
1

我試圖清理一個實體(即關係術語中的一個表)的集合,那些實體是Color的實例,我想運行一個使用Doctrine 2刪除所有未提及的Color's。問題是Color被系統中的許多其他實體引用。所以我能想到的兩種選擇:檢查與Doctrine 2的完整性約束違規

  1. 遍歷所有的顏色和我的系統上存在的其他實體特定Color引用手動檢查每一個,並且,如果沒有參照物,將其刪除。
  2. 迭代所有顏色並嘗試刪除一個顏色,如果存在對該顏色的引用,則捕獲EM由完整性約束違反引起的異常,所以我忽略失敗的顏色並繼續下一個。

很明顯,第二種選擇比第一種選擇更簡單,所以我試過了。我遇到的問題是,當一個實體刪除失敗時,EM引發異常,但也關閉了實體管理器,我不能再使用它來刪除剩餘的顏色!

我檢查commit方法UnitOfWork類的學說2,事實上...

try { 
    ... //Execute queries 

    $conn->commit(); 
} catch (Exception $e) { 
    $this->em->close(); 
    $conn->rollback(); 

    throw $e; 
} 

有什麼辦法來完成我想要做的(也許重啓實體管理器)?
你相信有更好的辦法嗎?
爲什麼學說有這種行爲?

同時請注意,我使用學說2 Symfony的2

回答

1

理想情況下,你會在你的關係定義orphanRemoval這樣你就不會需要去除打擾。除此之外,我現在可以想到3種解決方案..

首先,當您參考colors表時,您是否在ON DELETE中使用CASCADE

1)

如果使用CASCADE這裏描述我會建議實施學說的批處理:BULK DELETE但在這裏你$batchSize會完全1.

2)

我,不知何故,看到上面的解決方案效率不高,你也可以通過以下方式實現:

  • 通過這些實體引用Color實體並將Colorid收集到數組中。
  • 如果該數組不爲空,請執行:DELETE FROM AcmeDemoBundle:Color c WHERE c.id IN (:ids)並像往常一樣設置ids參數。

3)

還有另外一個解決方案,如果你使用CASCADE。您可以執行原始SQL

DELETE IGNORE FROM color; 

在這裏,引用的顏色不會被刪除,並會觸發一個錯誤,但由於IGNORE這將最終僅作爲警告。

希望一些這有助於....

+0

感謝您的解決方案,我真的不應該使用級聯刪除或'orphanRemoval',因爲我不想真的要刪除所有的孤兒顏色。我想我應該在之前提到它,但是爲了數據庫清理目的,任務只執行一次,因此,我要弄清楚第三種解決方案,或許我鬆散的DBMS可移植性,幸運的是DBMS需求已經定義好了! :) – eagleoneraptor

+0

啊是的...在這種情況下** 2)**最適合你... :) –

0

事情是這樣的:

// somewhere in ColorRepository.php 

$this->createQueryBuilder("o") 
    ->leftJoin("o.Relation1", "r1") 
    ->leftJoin("o.Relation2", "r2) 
    ->where("r1 IS NULL AND r2 IS NULL") 
    ->delete() ; 

這應該載入您的實體(彩色),只有當他們沒有與r1和r2的關係不再和刪除它們。

+0

這是一個有趣的解決方案,但是,你需要與所有實體顏色實體...對嗎? –

+0

謝謝,但通過模型設計,我不應該使用所有'顏色'反向關係。 – eagleoneraptor

+0

是的。我知道教義文件說這不是必需的,但我總是把它們放在一起,因爲我發現它們非常非常有用。 – Zeljko

相關問題