Метод репозитория не всегда дает ожидаемые результаты

1

У меня странная ошибка Symfony/Doctrine. Моя структура объектов выглядит следующим образом

class ClassA {

/**
* @ORM\ManyToOne(targetEntity="My\CoreBundle\Entity\ClassB", inversedBy="classAs", cascade={"persist"})
* @ORM\JoinColumn(nullable=false)
*/
private $classB;

}

class ClassB {

/**
 * @ORM\OneToMany(targetEntity="My\CoreBundle\Entity\ClassA", mappedBy="classB", cascade={"persist", "remove"})
 */
private $classAs;

/**
* @ORM\ManyToOne(targetEntity="My\CoreBundle\Entity\ClassC", inversedBy="classBs")
* @ORM\JoinColumn(nullable=false)
*/
private $classC;

}

class ClassC {

/**
* Inverse Side
* @ORM\OneToMany(targetEntity="My\CoreBundle\Entity\ClassB", mappedBy="classC", cascade={"persist", "remove"})
*/
private $classBs;

/**
* Inverse Side
* @ORM\OneToMany(targetEntity="My\CoreBundle\Entity\ClassD", mappedBy="classCs", cascade={"persist", "remove"})
*/
private $classDs;

}

class ClassD {

/**
* @ORM\ManyToOne(targetEntity="My\CoreBundle\Entity\ClassC", inversedBy="classDs")
* @ORM\JoinColumn(nullable=false)
*/
private $classC;

}

Я знаю, что в базе данных ClassA (id = 566208) связан с ClassD (id = 16286).

У меня этот очень простой метод в ClassARepository.

class ClassARepository extends EntityRepository
{
    public function myMethod()
    {
        $builder = $this->createQueryBuilder('classA');
        $query = $builder->getQuery();

        $classAs = $query->getResult();

        echo "<pre>";
        foreach ($classAs as $classA) {
            if ($classA->getId() == 566208)
            {
                echo "classA 566208\n";
                $classDs = $classA->getClassB()->getClassC()->getClassDs();
                $found = false;
                foreach ($classDs as $classD) {
                    if (16286 == $classD->getId()) {
                            $found = true;
                            echo "INFO 16286 found\n";
                    }
                }
                if (false == $found) echo "ERROR 16286 Not found\n";
            }
        }
        echo "</pre>";
  }
}

Когда я вызываю этот метод в контроллере, нет проблем

class MyController
{
    public function indexAction()
    {
        $this->getRepository('MyCoreBundle:ClassA')->myMethod();

    // [...]
    }
}

Результат:

classA 566208
INFO 16286 found

Но в другой части кода

class MyService
{
    private function myServiceMethod()
    {
        $this->doctrine->getManager()
                        ->getRepository('MyCoreBundle:ClassA')->myMethod();
    }
}

Результат:

classA 566208
ERROR 16286 Not found

Что может вызвать это? Я немного смущен и не знаю, надежна ли моя Доктрина.

Моя конфигурация "php": "> = 5.5", "symfony/symfony": "2.8. *", "Doctrine/orm": "~ 2.5",

Я сделал MySQLcheck, все выглядит нормально.

EDIT/TL;DR:

Этот код...

echo "<pre>";
echo "NORMAL\n";
$classC = $this->doctrine->getManager()->getRepository('MyCoreBundle:ClassC')->find(7);
$classDs = $classC->getClassDs();
$found = false;
foreach ($classDs as $classD) {
    if (16286 == $classD->getId()) {
            $found = true;
            echo "INFO 16286 found\n";
    }
}
if (false == $found) echo "ERROR 16286 Not found\n";

echo "INVERSED\n";
$classDs = $this->doctrine->getManager()->getRepository('MyCoreBundle:ClassD')->findBy(array("classC" => 7));
$found = false;
foreach ($classDs as $classD) {
    if (16286 == $classD->getId()) {
            $found = true;
            echo "INFO 16286 found\n";
    }
}
if (false == $found) echo "ERROR 16286 Not found\n";
echo "</pre>";

... дает...

NORMAL
ERROR 16286 Not found
INVERSED
INFO 16286 found
Теги:
doctrine
doctrine2

2 ответа

1
Лучший ответ

Проблема заключалась в том, что запросы были выполнены до вызова сервиса myMethod, а Doctrine поместили в кеш некоторые подчасти этих запросов.

Решение заключалось в том, чтобы попросить Entity Manager очистить кеш.

$this->doctrine->getManager()->clear();
$this->doctrine->getManager()
                    ->getRepository('MyCoreBundle:ClassA')->myMethod();
0

Если вы только запрашиваете этот идентификатор, вам не нужно и не следует перебирать каждую запись таблицы, если она не нужна. Что-то вроде этого:

$this->doctrine->getManager->getRepository->('MyCoreBundle:ClassA')->find(16286)

намного эффективнее. И вы можете выбрать entityManager изнутри репозитория и получить репозиторий для класса C и запросить его с идентификатором напрямую.

Вы уверены, что ничто не меняет отношения между двумя вызовами метода?

Я использую Доктрину в течение некоторого времени, а также в производстве, но у меня не было такой проблемы.

  • 0
    Нет, мне нужно зациклить все объекты ClassA, но я обнаружил, что чего-то не хватает для этого конкретного идентификатора 566208. Я не знаю, есть ли у других объектов такая же проблема.
  • 0
    Ничего не меняется между вызовами двух методов.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню