Ich habe eine Car
Entität mit einer Viele-zu-eins-Beziehung mit einer Entität Owner
. Wenn ich alle Autos auswähle, führt Doctrine eine Abfrage auf der Tabelle Car
und anschließend eine Abfrage auf der Owner
Tabelle für jedes Auto. So wird das Holen von N Autos zu N + 1 Anfragen anstelle einer einzelnen JOIN Abfrage zwischen den Car
und Owner
Tabellen.Doctrine2 Viele-zu-eins-Verknüpfung verwendet keine JOIN-Abfrage
Meine Einheiten sind wie folgt:
/** @Entity */
class Car {
/** @Id @Column(type="smallint") */
private $id;
/** @ManyToOne(targetEntity="Owner", fetch="EAGER")
@JoinColumn(name="owner", referencedColumnName="id") */
private $owner;
public function getId() { return $this->id; }
public function getOwner() { return $this->owner; }
}
/** @Entity */
class Owner {
/** @Id @Column(type="smallint") */
private $id;
/** @Column(type="string") */
private $name;
public function getName() { return $this->name; }
}
Wenn ich die Autos mit ihren Besitzern auflisten wollen, ich mache:
$repo = $em->getRepository('Car');
$cars = $repo->findAll();
foreach($cars as $car)
echo 'Car no. ' . $car->getId() .
' owned by ' . $car->getOwner()->getName() . '\n';
Das ist aber alles funktioniert sehr gut, abgesehen von der Tatsache, dass Doctrine gibt für jedes Auto eine Abfrage aus.
SELECT * FROM Car;
SELECT * FROM Owner WHERE id = 1;
SELECT * FROM Owner WHERE id = 2;
SELECT * FROM Owner WHERE id = 3;
....
Natürlich würde ich meine Abfrageprotokoll wie folgt aussehen wollen:
SELECT * FROM Car JOIN Owner ON Car.owner = Owner.id;
Ob ich fetch="EAGER"
oder fetch="LAZY"
spielt keine Rolle, und selbst wenn ich eine benutzerdefinierte DQL-Abfrage machen mit JOIN zwischen den beiden Entitäten veranlasst $car->getOwner()
immer noch Doctrine, die Datenbank abzufragen (es sei denn, ich verwende EAGER, in diesem Fall verursacht $repo->findAll()
alle von ihnen).
Bin ich einfach zu müde hier, und so soll es funktionieren - oder gibt es eine kluge Möglichkeit, Doctrine dazu zu zwingen, stattdessen die JOIN-Abfrage zu machen?
Sieht aus wie das auch der Fall in 2.x. ist Ich hatte versucht, die Abfrage 'SELECT c FROM Auto c JOIN c.owner o', die immer noch N + 1 Abfragen gemacht, aber deins funktioniert gut. Danke vielmals! Ich denke, ich muss nur damit leben, dass ich die findXxx-Methoden nicht verwende. – Frode
Für solche Convenience-Methoden würde ich vorschlagen, eine Style-Klasse "Service-Layer" oder "Repository" zu erstellen, die Aufgaben wie das Laden von Modellen übernimmt. Auf diese Weise können Sie die Abfrage auch problemlos wiederverwenden, ohne die DQL-Logik überall duplizieren zu müssen. –