禁用 Doctrine 查询缓存

Disable Doctrine query cache

在 Doctrine 存储库 class 中,以下代码产生以下结果:

$rsm = new ResultSetMapping;
$rsm->addEntityResult($this->_entityName, 'g');
$rsm->addFieldResult('g', 'geonameid', 'id');

$nativeQuery = $this->_em->createNativeQuery(
    "SELECT g.geonameid FROM mydb.geoname g WHERE g.geonameid = 2998268",
    $rsm
);

$r = $nativeQuery->getResult();

Debug::dump($r);

结果:

array(1) {
    [0]=>
    object(stdClass)#461 (20) {
        ["__CLASS__"]=>
        string(40) "My\Bundle\Entity\Geonames\Geoname"
        ["id"]=>
        int(2998268)
        ["name"]=>
        NULL
        ["asciiname"]=>
        NULL
        ["latitude"]=>
        NULL
        ["longitude"]=>
        NULL
        ["fclass"]=>
        NULL
        ["fcode"]=>
        NULL
        ["countryCode"]=>
        NULL
        ["cc2"]=>
        NULL
        ["admin1Code"]=>
        NULL
        ["admin2Code"]=>
        NULL
        ["admin3Code"]=>
        NULL
        ["admin4Code"]=>
        NULL
        ["population"]=>
        NULL
        ["elevation"]=>
        NULL
        ["gtopo30"]=>
        NULL
        ["timezone"]=>
        NULL
        ["moddate"]=>
        NULL
    }
}

这个(几乎)空的对象是正确的结果。这是我期望得到的。但是,如果我在代码前加上 $test = $this->find(2998268);,我的 $nativequery 结果不再为空:

array(1) {
    [0]=>
    object(stdClass)#424 (20) {
        ["__CLASS__"]=>
        string(40) "My\Bundle\Entity\Geonames\Geoname"
        ["id"]=>
        int(2998268)
        ["name"]=>
        string(8) "Limousin"
        ["asciiname"]=>
        string(8) "Limousin"
        ["latitude"]=>
        string(10) "45.7666700"
        ["longitude"]=>
        string(9) "1.7000000"
        ["fclass"]=>
        string(1) "A"
        ["fcode"]=>
        string(4) "ADM1"
        ["countryCode"]=>
        string(2) "FR"
        ["cc2"]=>
        string(0) ""
        ["admin1Code"]=>
        string(2) "B1"
        ["admin2Code"]=>
        string(0) ""
        ["admin3Code"]=>
        string(0) ""
        ["admin4Code"]=>
        string(0) ""
        ["population"]=>
        int(737001)
        ["elevation"]=>
        int(0)
        ["gtopo30"]=>
        int(534)
        ["timezone"]=>
        string(12) "Europe/Paris"
        ["moddate"]=>
        string(8) "DateTime"
    }
}

我高度怀疑我的 $nativequery 现在从某个缓存(我没有设置)中获取对象,但我不希望它这样做。我仍然想要与之前没有调用 find() 相同的结果。

我该怎么办?

我尝试了以下方法:

$r = $nativeQuery
        ->setCacheMode(Cache::MODE_GET)
        ->setCacheable(true)
        ->getResult();

但是我收到一条错误消息说 Call to undefined method Doctrine\ORM\NativeQuery::setCacheMode()

我也试过设置$nativeQuery->useResultCache(false)但是没有效果。

我正在使用以下版本的 Doctrine 组件:

doctrine/annotations           v1.2.6
doctrine/cache                 v1.4.1
doctrine/collections           v1.3.0
doctrine/common                v2.5.0
doctrine/dbal                  v2.5.1
doctrine/doctrine-bundle       v1.5.0
doctrine/doctrine-cache-bundle v1.0.1
doctrine/inflector             v1.0.1
doctrine/instantiator          1.0.5
doctrine/lexer                 v1.0.1
doctrine/orm                   v2.4.7

我的猜测是,当您调用 $this->find(2998268); 时,Doctrine 加载了完整的实体。然后,当您调用 NativeQuery 时,EntityManager 发现它已经在管理具有相同 ID 的完全相同的实体,并且 returns 已经水合的实体。如果您在 find() 和 NativeQuery 之间调用 EntityManager->clear(),您应该会得到预期的结果。

创建 EntityManager 的新实例。然后,将实体合并到这个新的 EntityManager 中。之后,调用clear方法,到"enforce loading objects from database".

 /**
  * @var \Doctrine\ORM\Configuration
  */
  $config = $em->getConfiguration();

  /**
   * @var \Doctrine\DBAL\Connection
   */
   $connection = $em->getConnection();

  /**
   * @var \Doctrine\ORM\EntityManager $em
   */
   $em = $this->getEntityManager()
              ->create($connection, $config);

   $entityClass = get_class($entity);
   $em->merge($entity);
   $em->clear($entityClass);
   $oldEntity = $em->find($entityClass, $entity->getId());