2015-08-28 158 views
1

我的問題 - 處理嘗試更改已更改的實體並使用最新的版本ID。當我在我的代碼在UnitOfWork的commit()上升OptimisticLockException中執行flush()並通過catch-all塊捕獲相同的地方時。並在這個捕獲主義關閉EntityManager。 如果我想跳過這個實體,並繼續從ArrayCollection另一個,我不應該使用flush()?如何在發生OptimisticLockException時避免關閉EntityManager?

嘗試重建的EntityManager:

}catch (OptimisticLockException $e){ 
    $this->em = $this->container->get('doctrine')->getManager(); 
    echo "\n||OptimisticLockException."; 
    continue; 
} 

,仍然可以得到

[Doctrine\ORM\ORMException] 
The EntityManager is closed. 

奇怪。

,如果我做

$this->em->lock($entity, LockMode::OPTIMISTIC, $entity->getVersion()); 

,然後做的flush()我得到OptimisticLockException和關閉實體管理器。 如果我做

$this->getContainer()->get('doctrine')->resetManager(); 
$em = $doctrine->getManager(); 

未註冊的這個實體管理器中的舊數據,我甚至不能寫在數據庫日誌,我得到錯誤:

[Symfony\Component\Debug\Exception\ContextErrorException] 
Notice: Undefined index: 00000000514cef3c000000002ff4781e 
+0

還是必須在我的代碼重新打開的EntityManager在catch塊的例子嗎? – Hayate

回答

1

您應該檢查實體版本,您嘗試刷新之前這是爲了避免例外。換句話說,如果鎖定失敗,則不應調用flush()方法。

您可以使用EntityManager#lock()方法檢查是否可以刷新實體。

/** @var EntityManager $em */ 
    $entity = $em->getRepository('Post')->find($_REQUEST['id']); 

    // Get expected version (easiest way is to have the version number as a hidden form field) 
    $expectedVersion = $_REQUEST['version']; 

    // Update your entity 
    $entity->setText($_REQUEST['text']); 

    try { 
     //assert you edit right version 
     $em->lock($entity, LockMode::OPTIMISTIC, $expectedVersion); 

     //if $em->lock() fails flush() is not called and EntityManager is not closed 
     $em->flush(); 
    } catch (OptimisticLockException $e) { 
     echo "Sorry, but someone else has already changed this entity. Please apply the changes again!"; 
    } 

入住主義文檔optimistic locking

+0

添加有問題的信息。 – Hayate

+1

我在文檔中看到,我明白這一點。我不想回顯「抱歉」的信息並停止工作。我得到大量數據,並且我不想再請求所有數據,因爲它們是單個實體。在catch塊EntityManager關閉。好的,我可以重置它並重新創建。但所有的數據在新的EntityManager中未註冊,我無法再使用這些數據。 – Hayate

+0

在我的示例中,我只對一個實體進行了lock()檢查,但在您的情況下,您需要對集合中的所有實體進行檢查。如果某個實體的鎖定失敗,則需要決定如何解決該問題(從數據庫重新加載實體,警告用戶等)。當任何實體未通過鎖定檢查時,您不應該調用flush()。 – kormik