marcv
marcv

Reputation: 1976

Disable Doctrine query cache

In a Doctrine repository class, the following code produces the following result:

$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);

Result:

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
    }
}

This (almost) empty object is a correct result. It's what I expect to get. However, If I prepend the code with a $test = $this->find(2998268);, my $nativequery result is not empty anymore:

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"
    }
}

I highly suspect that my $nativequery now fetches the object from some cache (which I did not set up), but I don't want it to. I still want the same result as if I hadn't called find() before.

How can I do?

I tried the following:

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

But I get an error message saying Call to undefined method Doctrine\ORM\NativeQuery::setCacheMode().

I also tried to set $nativeQuery->useResultCache(false) but with no effect.

I'm using the following versions of Doctrine components:

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

Upvotes: 2

Views: 12977

Answers (2)

Filipe Fernandes
Filipe Fernandes

Reputation: 317

Create a new instance of EntityManager. Then, merge the entity into this new EntityManager. After that, call clear method, to "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());

Upvotes: -2

Kevin Sharp
Kevin Sharp

Reputation: 529

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.

Upvotes: 11

Related Questions