Doctrine2 (Doctrine 2.1) désireux de chargement dans Symfony2
Disons que j'ai deux entités dans mon projet Symfony2 : Category
et Article
(une catégorie ayant de nombreux articles).
Dans mon CategoryRepository
, j'ai cette méthode:
findAllDummy(){
return $this->createQueryBuilder('c')
->leftJoin('c.Articles a')
->getQuery()->getResult();
}
Si je me souviens bien, dans Symfony1.4 (et la version correspondante de la Doctrine), les objets retournés ont leurs "articles" attribut rempli par le correspondant Article
objets.
Maintenant, dans Symfony2, des objets Proxy sont retournés.
Donc, si je boucle à travers une catégorie spécifique d'articles, autant de requêtes que d'itérations sera exécuté.
foreach($category->getArticles() as $article){
echo $article->getDoctrine()
->getRepository('')getTitle();
}
Je comprends que c'est Doctrine2.1 par défaut de chargement paresseux comportement.
Question 1: comment cela est-il une meilleure solution?
N des requêtes au lieu de 1.
J'ai essayé de forcer le chargement impatient de la manière suivante:
findAllDummy(){
return $this->createQueryBuilder('c')
->leftJoin('c.articles a')
->getQuery()
->setFetchMode('Category', 'articles', 'EAGER')
->getResult();
}
Mais le résultat reste le même.
Question 2: comment faire pour forcer le chargement impatient dans Doctrine2?
Vous devez vous connecter pour publier un commentaire.
Vous joindre à une table, mais vous n'êtes pas sélectionner quelque chose de lui. Ajouter
->addSelect('a')
à votre générateur de requêtes. Considérons deux requêtes SQL suivantes pour comprendre la différence:Avides/paresseux de se joindre a rien à voir avec les requêtes DQL. Il définit ce que devrait être chargé lorsque vous utilisez
$articleRepository->find(123)
.fetch=EAGER
sur les articles' relation, tous les articles seront chargés (et hydraté) lorsque vous appelezcategoryRepository->findOne(321)
EntityManager::find*()
. Vous avez juste besoin d'utiliser différents "outils":->addSelect(...)
en DQL etfetch="EAGER"
dansem->find()
.fetch="EAGER"
(avec les guillemets).addSelect
m'a aidé à obtenir monorderBy
de travailjoin
etselect
, nous n'avons pas besoinsetFetchMode()
Dans la partie où vous essayez de "force désireux de chargement" le problème peut être que vous utilisez le
fetchMode
méthode avec le mauvais type de variable pour la$fetchMode
argument. Vous passez une chaîne'EAGER'
mais la méthode n'a pas s'attendre à une chaîne mais un nombre entier.La méthode attend des constantes de la
ClassMetadata
classe:Dans la Doctrine de la documentation chapitre 14.7.6.6. Changer temporairement le mode de lecture en DQL vous pouvez voir un exemple sur la façon d'utiliser ceci:
Donc passer soit une référence à la constante ou un entier qui correspond à la mode que vous souhaitez utiliser.
Comme il est dit dans le la doctrine docs, désireux de chargement dans ce cas, ne fait aucune différence parce que vous en avez un-à-plusieurs relation entre la Catégorie et de l'Article.
Donc, contrairement à ce que l' @Crozin a dit, vous pouvez toujours désireux de chargement en DQL.
Si vous avez un un-à-un ou plusieurs-à-une relation, désireux de chargement permettra de résoudre le problème de faire des requêtes supplémentaires. Toutefois, afin de résoudre votre problème dans ce cas, vous devez utiliser
->addSelect('a')
comme @Crozin mentionné.C'est une meilleure solution parce que les jointures sont beaucoup plus cher que d'une simple requête. Même si cela peut sembler inefficace, il n'est pas beaucoup de déchets, et devient rapidement plus efficace lorsque vous n'êtes pas le chargement de tous les bits de chaque objet.