2015-08-28 86 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