如何在 SQL Server 的 Doctrine 2 中更改 DQL 查询中的 LockMode

Posted

技术标签:

【中文标题】如何在 SQL Server 的 Doctrine 2 中更改 DQL 查询中的 LockMode【英文标题】:How to change the LockMode in a DQL query, in Doctrine 2 for SQL Server 【发布时间】:2016-02-16 09:54:26 【问题描述】:

我需要更改 LockMode 以让 Doctrine 将“with(nolock)”行为添加到我在 Query 中使用的表中。

我会更好地解释这一点:

我有什么:

SELECT e FROM Porject:Example e

我想从 Doctrine 创建和执行 SQL 时得到什么:

SELECT e FROM example e WITH(NOLOCK)

我无法找到如何在任何地方更改 LOCKMODE,这变得很痛苦。

我尝试打开一个事务并执行setLockMode(LockMode::NONE),但它只是在第一个表(FROM 子句中的那个)之后添加了with(nolock),我需要它在每个表中添加它(连接上的表) )。

我真正拥有的:

SELECT e, o FROM Porject:Example e JOIN e.owner o

我做了什么:

  $dql='SELECT e, o FROM Porject:Example e JOIN e.owner o';
  $query = $this->getEntityManager()->createQuery($dql);
  try
     $this->getEntityManager()->getConnection()->beginTransaction();
     $result = $query ->setLockMode(LockMode::NONE)->getSQL();
     $this->getEntityManager()->getConnection()->commit();
   catch (\Exception $e) 
     $this->getEntityManager()->getConnection()->rollback();
     throw $e;
  

成为$result

SELECT c0_.prop1, c0_.prop2, c1_.prop1, c1_.prop2 
FROM examples c0_ WITH(NOLOCK) 
INNER JOIN owners c1_ ON c1_.id= c0_ownerId`

我所期待的:

SELECT c0_.prop1, c0_.prop2, c1_.prop1, c1_.prop2 
FROM examples c0_ WITH(NOLOCK) 
INNER JOIN owners c1_ WITH(NOLOCK) ON c1_.id= c0_ownerId`

注意双重WITH(NOLOCK)

可能的解决方案:

try 
    $this->getEntityManager()->getConnection()->beginTransaction();
    $this->getEntityManager()->getConnection()->setTransactionIsolation(\Doctrine\DBAL\Connection::TRANSACTION_READ_UNCOMMITTED);
    $result = $query->getArrayResult();
    $this->getEntityManager()->getConnection()->commit();
 catch (\Exception $e) 
    $this->getEntityManager()->getConnection()->rollback();
    throw $e;

但我不确定使用with(nolock) 是否与使用READ_UNCOMMITTED 相同隔离级别

将@chalasr 的答案设置为已接受的答案。创建另一个问题来解决实际问题:How perform lockmode:none on associations (join) with Doctrine2 and SQL Server

仅供参考。

【问题讨论】:

【参考方案1】:

有 4 个不同的LockMode

const NONE = 0;
const OPTIMISTIC = 1;
const PESSIMISTIC_READ = 2;
const PESSIMISTIC_WRITE = 4;

在documentation 中找到最合适的并像这样使用:

$query = $em->createQuery('SELECT e FROM Porject:Example e');
$query->setLockMode(LockMode::NONE);

【讨论】:

我只是在尝试,但它抱怨:“此操作需要一个开放的交易。”。 用新状态更新我的第一个 POST。问题没有完全解决。 啊,这真的是一个不同的问题......寻找将您的查询分成两部分,为每个设置锁定模式,我会寻找并回复您。 您应该针对如何在关联(加入)上执行锁定模式提出另一个问题 我尝试了不同的方法,我不知道它是否完全等效(编辑了第一篇文章)。非常感谢。

以上是关于如何在 SQL Server 的 Doctrine 2 中更改 DQL 查询中的 LockMode的主要内容,如果未能解决你的问题,请参考以下文章

使用 Symfony2 和 Doctrine 的 SQL Server 数据库连接

Doctrine - 如何打印出真正的 sql,而不仅仅是准备好的语句?

Symfony 和 Doctrine 1.2.2:如何获取 Doctrine_Query 对象的 SQL 子句?

如何删除学说 Doctrine Raw Sql 查询中的特定 dql 部分?

如何从 Doctrine sql 查询中映射列名?

Symfony2 & Doctrine:创建自定义 SQL 查询