原则2 ORM选择更新更新
2022-08-30 19:35:39
你能建议一种如何用教义来实施的方法吗?SELECT FOR UPDATE
我需要读取一个计数器值,然后在PHP代码中使用它,并在其他人(来自另一个进程)使用相同的值之前立即递增该值。
你能建议一种如何用教义来实施的方法吗?SELECT FOR UPDATE
我需要读取一个计数器值,然后在PHP代码中使用它,并在其他人(来自另一个进程)使用相同的值之前立即递增该值。
显然,Doctrine 2在MySQL中使用了LOCK IN SHARED MODE和Pessimistic read lock,这与SELECT FOR UPDATE不同。
看看当前稳定版本的来源,似乎在 Doctrine 中没有原生方法可以做到这一点(我不确定为什么 Doctrine 团队为 MySQL 选择了这种类型的锁)。
我使用本机 SQL 作为解决方法,它可以映射到传统实体,就像使用 DQL 一样:
<?php
$rsm = new ResultSetMappingBuilder($this->_em);
$rsm->addRootEntityFromClassMetadata('Model_Record_Delivery', 'u');
$query = $this->_em->createNativeQuery("SELECT * FROM delivery WHERE id = :id FOR UPDATE", $rsm);
$query->setParameter("id", $id);
$result = $query->getOneOrNullResult();
正如本杰明所指出的,PESSIMISTIC_WRITE就是你要找的。
使用 DQL
<?php
$query = $this->em->createQuery('SELECT e
FROM Application\Model\Entity\MyEntity e
WHERE e = :id');
$query->setParameter("id", $id);
$query->setLockMode(\Doctrine\DBAL\LockMode::PESSIMISTIC_WRITE);
不带 DQL
<?php
$entity = $em->find('Application\Model\Entity\MyEntity', $id, \Doctrine\DBAL\LockMode::PESSIMISTIC_WRITE);
此外,您必须在事务中使用该语句才能使其正常工作。
原则 2 实现了对实体的锁定支持:
<?php
use Doctrine\DBAL\LockMode;
use Doctrine\ORM\OptimisticLockException;
$theEntityId = 1;
$expectedVersion = 184;
try {
$entity = $em->find('User', $theEntityId, LockMode::OPTIMISTIC, $expectedVersion);
// do the work
$em->flush();
} catch(OptimisticLockException $e) {
echo "Someone else has already changed this entity. Apply the changes again!";
}
另外,你可以这样做,它抛出执行原始SQL:
$em->getConnection()->exec('LOCK TABLES table_name WRITE;'); //lock for write access
然后
$em->getConnection()->exec('UNLOCK TABLES;');