Ik heb een lijst met entities die ik op een pagina wil weergeven in een tabel. De entities hebben elk een aantal one-to-many relatie die ik ook als kolom wil weergeven in de tabel. Dit is een probleem omdat de tabel mogelijks honderden rijen bevat, en door lazy loading wordt er telkens per rij een extra query uitgevoerd om de relaties te fetchen.
Een oplossing om het aantal queries terug te brengen zou het toevoegen van fetch joins kunnen zijn, maar dit wil ik vermijden omdat dit op zich ook performance problemen geeft bij het hydraten naar objecten.
Ik zat dus te denken aan een custom repository methode waaraan ik voor de verkregen lijst met entities meegeef, die in één enkele query de many-to-one relatie ophaalt (de entities voor de tabel zijn "cards" en die uit de relatie "variantTypes"):
Ik maak me hierbij de bedenking dat dit omslachtig en niet echt elegant is (zeker als ik dit eventueel voor meerdere relaties moet doen). Kan doctrine dit niet op een andere manier doen waar ik (blijkbaar) niet van weet? Ook vraag ik me af of al deze iteraties wel een betere performance geven dan het probleem dat ik probeer op te lossen (moet dit nog testen).
Een oplossing om het aantal queries terug te brengen zou het toevoegen van fetch joins kunnen zijn, maar dit wil ik vermijden omdat dit op zich ook performance problemen geeft bij het hydraten naar objecten.
Ik zat dus te denken aan een custom repository methode waaraan ik voor de verkregen lijst met entities meegeef, die in één enkele query de many-to-one relatie ophaalt (de entities voor de tabel zijn "cards" en die uit de relatie "variantTypes"):
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
| public function getAndAssignVariantTypes(array $cards) : void { $dql = ' SELECT card.id AS cardId, cardVariantType.id as cardVariantTypeId FROM AppBundle:Card card INNER JOIN card.variantTypes cardVariantType WHERE card.id IN (:cardIds) ORDER BY card.id ASC, cardVariantType.id ASC '; $cardsIndexedPerId = array(); $cardIds = array(); foreach ($cards as $card) { $cardId = $card->getId(); $cardsIndexedPerId[$cardId] = $card; $cardIds[] = $cardId; } $query = $this->getEntityManager()->createQuery($dql); $query->setParameter('cardIds', $cardIds); $cardVariantTypes = $this->getEntityManager()->getRepository(\AppBundle\Entity\CardVariantType::class)->findAllIndexedPerId(); $cardVariantTypesPerCardId = array(); foreach ($query->getResult() as $queryResultRow) { $cardId = $queryResultRow['cardId']; if (!isset($cardVariantTypesPerCardId[$cardId])) { $cardVariantTypesPerCardId[$cardId] = array(); } $cardVariantTypesPerCardId[$cardId][] = $cardVariantTypes[$queryResultRow['cardVariantTypeId']]; } foreach ($cardsIndexedPerId as $cardId => $card) { $card->setVariantTypes($cardVariantTypesPerCardId[$cardId]); } } |
Ik maak me hierbij de bedenking dat dit omslachtig en niet echt elegant is (zeker als ik dit eventueel voor meerdere relaties moet doen). Kan doctrine dit niet op een andere manier doen waar ik (blijkbaar) niet van weet? Ook vraag ik me af of al deze iteraties wel een betere performance geven dan het probleem dat ik probeer op te lossen (moet dit nog testen).