Учитывая этот код, Doctrine запускает столько запросов, сколько строк у меня в table2
$qb = $this->getModelManager()->createQuery($er->getClassName(), 't1')->getQueryBuilder();
$qb->select('t1, t2, t3')
->innerJoin('table1.table2', 't2');
->innerJoin('table2.table3', 't3')
->where('t3.id = :foo')
->setParameter('foo', $foo);
каждый запрос похож на этот:
SELECT t0.id AS id_1,
t0.name AS name_2,
t0.slug AS slug_3,
t0.description AS description_4,
t0.visible AS visible_5
FROM table2 t0
WHERE t0.id = ?
и это сущности:
ТАБЛИЦА 1: основная сущность, ведьма, связана с таблицей 2 с помощью manyToOne, если я сделаю innerJoin с таблицей 2, Doctrine будет действовать, как ожидалось (1 запрос)
/**
* @ORM\Entity(repositoryClass = "Table1Repo")
* @ORM\Table(name = "table1")
*/
class table1 extends BaseTable1 implements table1Interface
{
/**
* @ORM\Id
* @ORM\Column(type = "integer")
* @ORM\GeneratedValue
*/
protected $id;
/**
* @ORM\Column(type = "string", length=255)
* @Gedmo\Versioned
*/
protected $name;
/**
* @ORM\ManyToOne(targetEntity = "table2", inversedBy = "tables1")
* @ORM\JoinColumn(name = "table2_id", referencedColumnName = "id", onDelete = "CASCADE")
*/
protected $table2;
}
ТАБЛИЦА 2, связанная с первой таблицей от OneToMany и с таблицей 3 от ManyToMany.
/**
* @ORM\Entity(repositoryClass = "table2Repository")
* @ORM\Table(name = "table2")
*/
class table2 extends Basetable2
{
/**
* @ORM\Id
* @ORM\Column(type = "integer")
* @ORM\GeneratedValue
*/
protected $id;
/**
* @ORM\ManyToMany(targetEntity = "table3", inversedBy = "table2s")
* @ORM\JoinTable(name = "table3_table2")
*/
protected $table3;
/**
* @ORM\OneToMany(targetEntity = "table1", mappedBy = "table2")
* @Accessor(getter = "getTables1")
*/
protected $tables1;
}
ТАБЛИЦА 3: они связаны с таблицей 2 отношением ManyToMany. Когда я делаю innerJoin с таблицей 2, Doctrine по-прежнему действует так, как ожидалось, выполняя только один запрос
/**
* @ORM\Entity(repositoryClass = "table3Repo")
* @ORM\Table(name = "table3")
* @Gedmo\Loggable
*/
class table3 extends Basetable3
{
/**
* @ORM\Id
* @ORM\Column(type = "integer")
* @ORM\GeneratedValue
*/
protected $id;
/**
* @ORM\ManyToMany(targetEntity = "table2", mappedBy = "tables3")
* @ORM\JoinTable(name = "table3_table2")
*/
protected $tables2;
}
Итак, когда я добавляю оба innerJoins в конструктор запросов, Doctrine выполняет только один запрос, но когда я добавляю предложение WHERE, когда Doctrine выполняет 279 запросов, по одному на строку в table2, ведьма связана с table1 через oneToMany и с table3 пользователя ManyToMany.
Другой важный момент заключается в том, что построитель запросов выполняется под опцией поля query_builder SonataAdmin.
Я не могу понять, почему у меня такое поведение, есть подсказка?
Ну, я понимаю, что гидратация manyToMany включает в себя запрос к средней таблице между двумя объектами, но это не то, что делает ORM, она извлекает все данные из одной из таблиц и извлекает столько объектов, сколько строк в таблице, и вот чего я не понимаю. Фактически, запросы выполняются, когда я обрабатываю данные, которые уже получены с помощью внутренних соединений.
Запросы являются результатом не самого запроса, а обхода графа объектов в представлении.






Когда вы запускаете запрос, у вас всегда должен быть корневой объект, который присоединяется к другим. В вашем случае это table1. После выборки, на основе метаданных запроса и объекта, Doctrine попытается создать объект для каждого экземпляра root, но если не указано иное на этом остановится. Фактически, для каждого подобъекта (например, table2) он будет создавать фиктивные «прокси-объекты», которые едва ли являются поверхностными представлениями и должны быть разрешены из БД всякий раз, когда пытается их разыменовать. Процесс преобразования результатов БД в объекты известен как гидратация объекта.
Чтобы выполнить гидратацию подобъектов, вам нужно также «выбрать» подобъект:
$qb->select('t1', 't2', 't3')
->innerJoin('t1.table2', 't2');
->innerJoin('t2.table3', 't3')
->where('t3.id = :foo')
->setParameter('foo', $foo);
Обратите внимание, чтобы не сходить с ума, получая все, так как это занимает больше времени и потребляет значительно больше оперативной памяти. Настраивайте свой запрос до тех пор, пока не достигнете желаемого (логики и производительности).
Надеюсь это поможет...
Уже пробовал, но все равно схожу с ума от запросов, все равно спасибо.
Хм, если я не ошибаюсь, вы не можете присоединиться по «table1.id», так как это не относительный атрибут. Я скорректировал ответ, чтобы отразить структуру сущностей ... Можете попробовать?
сделал, и ничего, обновил вопрос. еще раз спасибо.
Это кажется довольно странным. По общему мнению, это должно работать. Есть ли еще какая-нибудь информация по этой проблеме, которой вы могли бы поделиться?
Это довольно стандартное поведение любого ORM. Прочтите, как работать с Коллекции в Doctrine.