禁用Doctrine查询缓存

时间:2015-07-28 14:45:54

标签: symfony caching doctrine-orm doctrine

在Doctrine存储库类中,以下代码生成以下结果:

$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

2 个答案:

答案 0 :(得分:3)

My guess is that when you call $this->find(2998268);, Doctrine loads the full entity. Then when you call the NativeQuery, the EntityManager finds that is is already managing the exact same entity with the same id, and returns the already hydrated entity. If you call EntityManager->clear() in between find() and your NativeQuery, you should get your expected result.

答案 1 :(得分:-1)

创建EntityManager的新实例。然后,将实体合并到这个新的EntityManager中。之后,调用clear方法,“强制从数据库加载对象”。

 /**
  * @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());