2017-02-02 8 views
0

Использование конструктора запросов стандартного менеджера Symfony3, я создать этот запрос:Doctrine2 неправильно кэширует результат запроса

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

Это в основном выбирает «а», родительский объект, а «а2», дочерний объект; оба они принадлежат к одному классу.

Когда я запускаю этот запрос, используя 2 в качестве параметра «id», запрос корректно увлажняет результаты, возвращая мне единственный результат, где a.id = 1 и a.id = 2.

Сразу после этого я повторно запускаю запрос 3 в качестве id; на этот раз результат должен быть одним, где a.id = 1 и a2.id = 3, но фактический результат тот же, что и при id = 2.
Если я только запускаю запрос, где id = 3, результат, опять же, правильно гидратируется.

Мое лучшее предположение состоит в том, что доктрина кэширует результат и по какой-то причине фактически не выполняет запрос при изменении идентификатора (несмотря на то, что дамп параметра показывает правильное значение в поле id);
Поиск в Интернете очень слабых результатов; я нашел старые (и исправленные) сообщения об ошибках об этом, и любое отключение кэша от запроса не принесло никаких улучшений.

Я могу просто решить проблему, только вытаскивая основную сущность, а затем вручную просматривая дочерние, но мне бы очень хотелось узнать, есть ли способ локально отключить кеш или какой-либо другой вид db-side.

EDIT: У меня эта проблема в тестовой среде; 2 запроса выполняются в 2 разных (но последовательных) вызовах функций

+0

Вы перестраиваете полный запрос с помощью построителя запросов или повторно используете первый объект запроса? – aferber

+0

Я полностью перестраиваю запрос; я предоставил дополнительную информацию, отредактировав вопрос – Vkfan

+0

Вы можете изменить строку с помощью '-> orX' в' -> andWhere ('a2.id =: id') '.Как ваш запрос написан, OR пытается выбрать все кортежи '(a, a2)', где либо 'a', либо' a2' имеет id ': id'. Единственная причина, по которой вы получаете результат с помощью 'a.id == 1', заключается в том, что ваш запрос также содержит' -> andWhere ("a =: anagrafica") '. В основном, в выражениях SQL вы запрашиваете '... AND a.id = 1 AND (a.id = 2 OR a2.id = 2) ...'. Очевидно, что 'a.id = 2' никогда не может применяться, поскольку это противоречит' a.id = 1'. – aferber

ответ

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(), будут не быть сохранены в базе данных на следующем flush(), так как диспетчер объектов больше ничего не знает об этих объектах. Вы также можете удалить один объект из менеджера, вызвав $em->detach($entity), однако это может привести к проблемам, если вы отделите только родительский объект, вам может потребоваться отделить всю иерархию объектов от вашего первого запроса.

+0

Спасибо за ответ, но к несчастью это не то, что я ищу; Я уже изучал инкрементную гидратацию, и я на 100% уверен, что это не то, что произошло во время тестов; Сброс symfony показал мне существование единственного дочернего объекта, а также того, у кого неправильный идентификатор. Кроме того, я уже пробовал $ em-> clear, и я не могу отсоединиться, потому что проблема возникает между двумя разными клиентскими вызовами (несмотря на то, что они находятся в одной и той же тестовой функции). На стороне, если я удаляю orX, затем увлажняю весь entitiy и вручную цикл коллекции, при некоторых poing я нахожу правильный результат. – Vkfan

 Смежные вопросы

  • Нет связанных вопросов^_^