禁用 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());
在 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());