我必須簡單的實體:日誌和用戶。 日誌與Entity具有ManyToOne關係。如何使用inner join時優化多個Doctrine查詢?
Log:
type: entity
repositoryClass: LogRepository
id:
id:
type: integer
generator:
strategy: AUTO
fields:
message:
type: string
manyToOne:
user:
targetEntity: User
joinColumns:
user_id:
referencedColumnName: id
我用例是顯示日誌列表和一個或兩個有關用戶(如他的名字和他的例如電子郵件)
如果我使用findall
方法,Symfony的調試工具欄告訴我,學說執行了很多查詢。一個查詢爲我提供日誌,併爲每個用戶執行一個查詢!這當然不好,因爲我認爲我可以有一千個日誌。我不想超載我的數據庫服務器。這個問題似乎很容易解決。但我正在尋找一段時間,結果似乎是「不好的做法」。
於是,我開始使用的QueryBuilder在LogRepository類寫一個新的方法:
public function getLog(){
$qb = $this->createQueryBuilder('l')
->select('l')
->innerJoin(
'ApplicationSonataUserBundle:User', 'u',
Expr\Join::WITH,'l.user = u.id')
;
return $qb->getQuery()->getResult();
}
我仍然有同樣的問題。我已經將我的方法上的選擇參數更改爲:
public function getLog(){
$qb = $this->createQueryBuilder('l')
->select('l','u')
->innerJoin('ApplicationSonataUserBundle:User','u',
Expr\Join::WITH,'l.user = u.id')
;
return $qb->getQuery()->getResult();
}
Eureka?好的,我只有一個查詢,但我的方法並沒有只返回日誌,但用戶太...所以我的樹枝模板崩潰,因爲我的循環包含用戶,而不僅僅是日誌。當這是一個用戶時,我的視圖崩潰,因爲我想寫消息字段。 (Log.message的存在,但User.message不是有效的領域,當然)。
它的工作原理相當不錯,如果我改變一次我的方法有循環過濾我的結果:
public function getLog(){
$qb = $this->createQueryBuilder('l')
->select('l','u')
->innerJoin('ApplicationSonataUserBundle:User','u',
Expr\Join::WITH,'l.user = u.id')
;
//THE STRANGE LOOP
$results = array();
foreach ($qb->getQuery()->getResult() as $result){
if ($result instanceof Log){
$results[] = $result;
}
};
return $results;
}
我只有一個查詢,這是我正在尋找的。我的樹枝模板不會崩潰,因爲我的數組只包含Log。
那麼,有什麼事?它有效,但我認爲這不是好的/最佳實踐。
有人可以解釋我一個更好的辦法,更好的做法是使用內部聯接查詢,最大限度地減少執行查詢,並有一個包含日誌的唯一實例的ArrayCollection結果?
和 - 如果你知道如何使用它,要小心:如果你真的只需要用戶的一個或兩個屬性(和用戶,否則是一個非常大的對象),你可以使用部分語法只需要取用戶的屬性。 – LBA
非常感謝!即使工作完成,我也知道我做錯了。作爲我的使用案例,學說似乎很簡單。而我的代碼似乎太複雜。謝謝。這十分完美 ! @LBA:謝謝我會看看部分語法。用戶可以是一個大對象,我只需要他的名字和他的郵件。頭像,blob信息不必檢索。感謝您的信息! –