[英]Doctrine2 strictly trying to inser t NULL when i use one-to-one and many-to-one relations
[英]Doctrine2 many-to-one association won't use JOIN query
我有一個與實體Owner
多對一關系的Car
實體。 如果我選擇所有汽車,Doctrine會在Car
表上執行一次查詢,然后在Owner
表上對每輛汽車進行一次查詢。 因此,獲取N個汽車變為N + 1個查詢,而不是Car
和Owner
表之間的單個JOIN查詢。
我的實體如下:
/** @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; }
}
如果我想與他們的車主列出汽車,我會這樣做:
$repo = $em->getRepository('Car');
$cars = $repo->findAll();
foreach($cars as $car)
echo 'Car no. ' . $car->getId() .
' owned by ' . $car->getOwner()->getName() . '\n';
現在這一切都很有效,除了Doctrine為每輛車發出查詢這一事實。
SELECT * FROM Car;
SELECT * FROM Owner WHERE id = 1;
SELECT * FROM Owner WHERE id = 2;
SELECT * FROM Owner WHERE id = 3;
....
當然我希望我的查詢日志看起來像這樣:
SELECT * FROM Car JOIN Owner ON Car.owner = Owner.id;
我是否有fetch="EAGER"
或fetch="LAZY"
並不重要,即使我在兩個實體之間使用JOIN進行自定義DQL查詢, $car->getOwner()
仍會導致Doctrine查詢數據庫(除非我使用EAGER,在這種情況下$repo->findAll()
導致所有這些)。
我在這里太累了,這是它應該工作的方式 - 或者是否有一種聰明的方法來迫使Doctrine進行JOIN查詢?
至少在1.x Doctrine中如果要查詢相關對象,則必須使用DQL。 對於您的情況,DQL查詢看起來像這樣:
//Assuming $em is EntityManager
$query = $em->createQuery('SELECT c, o FROM Car c JOIN c.owner o');
$cars = $query->execute();
先運行DQL查詢,然后選擇與所有者聯接的所有汽車(DQL JOIN)。 將所有者放在select()
。
// preload cars
$qb = $em->createQueryBuilder()
->select('car, owner')
->from('\Entity\Car', 'car')
->leftJoin('c.owner', 'owner');
$query = $qb->getQuery();
// the following seems not needed, but I think it depends on the conf
$query->setFetchMode("\Entity\Car", "owner", "EAGER");
$query->execute(); //you don't have to use this result here, Doctrine will keep it
然后,Doctrine 2將執行JOIN(通常更快,因為它需要更少的db查詢,具體取決於記錄的數量)。 現在啟動你的foreach
,Doctrine將在內部找到實體,當你需要owner
時它不會運行單個查詢。
監控每次更改后的查詢次數(例如,mysql常規日志)
您的查詢...
$car->getOwner() // "go and fetch this car's owner"
...在foreach循環中,因此它肯定會多次發出查詢。
如果你正在編寫自定義DQL來處理這個問題,那么$car->getOwner()
就不應該具有這個功能了。 這是Car類的功能。 您要編寫的自定義DQL將模仿您指出的確切SQL查詢並有效地完成連接。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.