使用Symfony3的标准管理器查询构建器,我创建了这个查询:
$anagrafica = $em->createQueryBuilder()
->select("a, rel, a2")
->from("AppBundle\Entity\Anagrafica\anagrafica", "a")
->leftJoin("a.relazioniDa", "rel")
->leftJoin("rel.anagrafica_figlio", "a2")
->where("a.stato = :actStatus")
->andWhere("a = :anagrafica")
->andWhere($em->createQueryBuilder()->expr()->orX("a.id = :id", "a2.id = :id"))
->setParameter("anagrafica", $anagraficaInserente)
->setParameter("actStatus", $actStatus)
->setParameter("id", $id)
->getQuery()->getResult();
这基本上选择" a",一个父实体," a2",一个子实体;他们俩都属于同一个班级。
当我使用2作为" id"运行此查询时参数,查询正确地为结果提供水合,返回一个结果,其中a.id = 1和a.id = 2.
之后,我立即重新运行查询设置3作为id;这次,结果应该是单一的,其中a.id = 1和a2.id = 3,但实际结果与id = 2时相同。
如果我只运行id = 3的查询,结果再次正确补充。
我最好的猜测是,doctrine正在缓存结果,并且由于某种原因,当我更改id时,它实际上并没有重新执行查询(尽管参数转储在id字段中显示正确的值);
在线搜索结果非常糟糕;我发现了有关此问题的旧(和修复)错误报告,并且对查询禁用的任何类型的缓存都没有带来任何改进。
我只能通过获取主实体来解决问题,然后手动查看子实体,但我真的很想知道那里有一种本地禁用缓存的方法,或者其他一些数据库端解决方案。
编辑: 我在测试环境中遇到过这个问题; 2个查询在2个不同(但连续)的函数调用中执行
答案 0 :(得分:0)
您的问题不是某种查询缓存,而是对实体管理器如何工作的误解。
实体管理器跟踪从数据库加载的所有对象。当你的第二个查询的结果被水合时,它会看到这个特定的a
实体已经被水合,因此它为你提供了第一个查询已经返回的完全相同的PHP对象实例($a_from_first_query === $a_from_second_query
)。第二个结果中的rel
和a2
个对象会添加到$a->relazioniDa
集合中,该集合已包含第一个查询中的rel
和a2
。在第二次查询后,$a->relazioniDa[0]->anagrafica_figlio->id
将为2,$a->relazioniDa[1]->anagrafica_figlio->id
将为3.这也称为增量水合。
为了防止这种情况,您可以通过调用$em->clear()
清空两个查询之间的实体管理器。但是,您必须记住,这意味着在clear()
之前检索到的任何实体的更改将 not 保存到下一个{{ 1}},因为实体管理器不再知道有关这些对象的任何信息。您也可以通过调用flush()
从管理器中删除单个对象,但是如果您只分离父对象,则可能会导致问题,您可能必须从第一个查询中分离整个对象层次结构。