2017-05-05 65 views
1

我試圖在UniqueConstraintViolationException後繼續堅持實體在Doctrine ORM中的UniqueConstraintViolationException之後繼續保持實體嗎?

我正在上傳代碼列表並使用Doctrine ORM實體保存到數據庫中。

我想避免重複的代碼並繼續保存其他代碼。

首先查詢代碼是否在數據庫中,然後保存的簡單解決方案是好的,但它可能只是忽略異常並繼續?避免查詢數據庫。

foreach($uploadEntities as $entity){ 
try{ 
    $em->persist($entity); 
}catch(UniqueConstraintViolationException){ 
    //ignore 
} 
} 
+0

基本上沒有。拋棄異常會有效地破壞實體經理。只是其中的一件事。唯一的辦法是成立一個全新的實體經理並重新開始。試圖持續使用驗證系統來檢查唯一性。 – Cerad

回答

3

您必須清除$em->flush()調用中的例外情況。

考慮到在這樣的異常之後,事務回滾並且實體管理器關閉。

您應該然後用

$em = $this->getDoctrine()->resetManager(); 

重新打開它,但要知道,作爲該處理的結果,EntityManager的所有先前管理或刪除實例變得脫離。分離對象的狀態將成爲事務回滾點的狀態。對象的狀態不會回滾,因此對象現在與數據庫不同步。應用程序可以繼續使用分離的對象,知道它們的狀態可能不再準確。

因此,您應該從dB中重新讀取您需要處理的所有先前提取的對象。

分別刷新每個持久對象可能很方便,以便您可以跳過Bad對象並繼續。

http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/transactions-and-concurrency.html#exception-handling

1

我的建議是不要使用這種類型的工作流程中,由於性能原因是更好地檢查數據庫中所有存在的代碼,然後忽略存在的。

$em->createQueryBuilder() 
      ->select('code.code') 
      ->from(Code::class, 'code') 
      ->where($qb->expr()->in('code.code', $importedCodes)); 

$existentCodes = array_column($qb->getQuery()->getArrayResult(), 'code'); 
if (in_array($currentCode, $existentCodes)){ 
    continue; 
} 
在另一方面

可以在事務包裹這種類型的工藝。如果您要上傳許多代碼,請使用批處理或其他任何方式來提高性能。