Zend FR

Consultez la FAQ sur le ZF avant de poster une question

Vous n'êtes pas identifié.

#1 30-07-2014 16:15:42

Seryus
Membre
Date d'inscription: 17-02-2012
Messages: 128

QueryBuilder vs NativeQuery & ResultSetMapping

Bonjour,

J'utilisais toujours le QueryBuilder depuis que j'utilise Doctrine pour faire mes requêtes (sauf si elles ne peuvent pas être gérées avec Doctrine) et je pensais que c'était la seule façon de faire pour récupérer une entité plutôt qu'un tableau. Mais récemment j'ai vu qu'on pouvait utiliser le ResultSetMapping pour mapper les champs du résultat de la requête à l'entité.

Les intérêts de cette façon de faire sont multiples :
_ Des requêtes plus performantes,
_ On ne se prend plus la tête avec le QueryBuilder/DQL
_ On évite les limitations de Doctrine (je pense par exemple à UNION qui n'est pas géré),
_ On récupère exactement ce qu'on veut du résultat (entité complète ou non),
_ Et on conserve le résultat sous la forme d'objets PHP plutôt que d'un tableau

Le seul inconvénient c'est qu'on doit créer un ResultSetMapping à chaque fois et mapper tous les champs qu'on souhaite récupérer.

Je me posais donc la question, pour quelle(s) raison(s) on devrait utiliser le QueryBuilder plutôt que les requêtes natives ?

Merci de votre réponse !

Hors ligne

 

#2 30-07-2014 17:17:42

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: QueryBuilder vs NativeQuery & ResultSetMapping

Salut je maitrise pas assez Doctrine pour pouvoir te conseiller une solution ou une autre faut que tu fasses un peu de recherche dans la doc doctrine tu devrais trouver facilement smile.

J'ai trouvé ça rapidement mais ça parle pas de la comparaison avec le QueryBuilder http://doctrine-orm.readthedocs.org/en/ … e-sql.html

Hors ligne

 

#3 30-07-2014 17:50:12

Seryus
Membre
Date d'inscription: 17-02-2012
Messages: 128

Re: QueryBuilder vs NativeQuery & ResultSetMapping

Oui c'est ici que j'ai vu comment utiliser le ResultSetMapping big_smile Je pense que je vais me passer du QueryBuilder à l'avenir, je n'ai rien trouvé qui conseille de l'utiliser. D'ailleurs c'est même plus pratique pour debugger vu qu'on a directement la requête SQL sous les yeux smile

Hors ligne

 

#4 30-07-2014 23:45:43

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: QueryBuilder vs NativeQuery & ResultSetMapping

Tu l'as aussi avec le QueryBuilder il suffit de faire $qb->getSql() smile.

Hors ligne

 

#5 31-07-2014 10:12:31

Seryus
Membre
Date d'inscription: 17-02-2012
Messages: 128

Re: QueryBuilder vs NativeQuery & ResultSetMapping

Oui mais... il faut le faire quoi tongue

Hors ligne

 

#6 31-07-2014 12:17:10

Splyf
Membre
Date d'inscription: 24-10-2013
Messages: 115

Re: QueryBuilder vs NativeQuery & ResultSetMapping

Salut,

Quel est l'interet du queryBuilder & du DQL?
déjà, tu peut renommé un champ coté mysql, et ne l'indiqué que dans la propriété de l'entité correspondante, sans avoir besoin de réécrire toute tes requête.

En suite, c'est la possibilité de créer des algorithme complexe sans te soucié de la syntaxe ou de l'ordre d'ajout des instructions!

dans le cadre d'un simple "select * from matable".... pas grand interet en effet.

Par contre, imagine un formulaire de recherche, avec 1 déroulant, des bouton radio, et 1 champ de texte.
Et il sont tous facultatif. De plus, 7 tables sont impliqué dans les critère cette recherches....mais tu n'affichera que le contenu de 4 champs répartie sur 2 tables.
Tu veut de plus pouvoir le trié comme tu veut, selon différent champs.
Et bien sur, vient le problème de pagination...
Enfin 2500 personne effectue une recherche par jour et il faut donc qu'elle sois très performante (donc le faire en moins de requêtes possible)...
Je sais pas si tu a déjà essayé en sql brute, mais produire une requête sql de 25lignes selon un algorithme aussi complexe, et que la dite requête ne prenne pas plus de 0.01 S...bin c'est l'orreur!!

En dQL, pas de problème d'optimisation, de syntaxe, ect, ect.

_ On évite les limitations de Doctrine (je pense par exemple à UNION qui n'est pas géré),

Pourquoi le UNION n'est pas géré? je n'y mettrai pas ma main a coupé, mais je suis quasiment sur que c'est parce-que le UNION est le meilleur moyen de faire une requête inutilement lourde :
Un union commence par exécute chaque requête séparément, puis effectue un dernier traitement pour n'avoir qu'un seul résultat. C'est inutile, car dans 99% des cas, tu peut t'en passé et n'écrire qu'une seul requête (oui par contre en se prenant la tête, mais tu essayera c'est casiement toujours possible).
Un bon gestionnaire de BDD te dira toujours que le UNION n'est a utilisé qu'en ultime recours smile

_ On récupère exactement ce qu'on veut du résultat (entité complète ou non),

c'est le cas avec le DQL, en changeant le mode d'hydration. C'est pas la syntaxe exact mais par exemple:
$qb->getQuery()->getResult(Query::HYDRATE_ARRAY);
-> et pouf tu a un tableau associatif
De plus avec le lazy loading, tu n'a jamais d'entité complete chargé, uniquemement se que tu demande et ce a la volé smile

_ Des requêtes plus performantes,

yikes
Coté php, surment (et encore sa doit pas être très visible). Mais coté mysql? Je croyai que le DQL cherchai à produire du sql performant=( , notalement en utilisant pas de UNION (hihi ^^).
Peut tu sité ta source? (je suis confronté a des souci de perf de temps en temps donc si il me suffit de passé au sql brute...)

Autre chose pour les limitation de doctine, je te conseille de  te documenté sur les fonction AST personalisable, qui te permettent de créer toi même toute les insctruction qu'il manque a d'octrine smile
http://docs.doctrine-project.org/en/2.0 … lkers.html

Dernière modification par Splyf (31-07-2014 12:22:12)

Hors ligne

 

#7 31-07-2014 14:17:30

Seryus
Membre
Date d'inscription: 17-02-2012
Messages: 128

Re: QueryBuilder vs NativeQuery & ResultSetMapping

Splyf a écrit:

En suite, c'est la possibilité de créer des algorithme complexe sans te soucié de la syntaxe ou de l'ordre d'ajout des instructions! dans le cadre d'un simple "select * from matable".... pas grand interet en effet.

Bah tu vois je pense tout le contraire de Doctrine big_smile Si tu veux faire une requête simple c'est vraiment pratique de faire $entityManager->find() par exemple plutôt que d'écrire une requête, par contre si tu veux faire une requête complexe ou spécifique, c'est galère sad

Splyf a écrit:

il faut donc qu'elle sois très performante (donc le faire en moins de requêtes possible)

Plus performante ne veut pas forcément dire le moins de requêtes possibles wink Et si tu te bases sur ça, j'ai eu des cas où Doctrine me faisait 30 requêtes pour récupérer quelque chose que j'aurais pu avoir en une seule (certes j'avais oublié des jointures et du coup à chaque fois que je faisais un $entity1->getEntity2() il me faisait une requête tongue mais même en ayant ajouté les jointures il ne me l'a pas fait en une seule requête neutral).

Splyf a écrit:

Pourquoi le UNION n'est pas géré? je n'y mettrai pas ma main a coupé, mais je suis quasiment sur que c'est parce-que le UNION est le meilleur moyen de faire une requête inutilement lourde

Je n'en suis pas si sûr, dans le seul cas d'UNION que j'ai utilisé je l'ai fait car j'utilise MySql et que la réflexivité n'est pas bien géré sur celui-ci. J'aurais aussi pu le faire en une requête avec des IN, mais niveau performance des requêtes avec "IN (SELECT...)" sont moins performantes que d'utiliser 2 requêtes voire un UNION.

Splyf a écrit:

Autre chose pour les limitation de doctine, je te conseille de  te documenté sur les fonction AST personalisable, qui te permettent de créer toi même toute les insctruction qu'il manque a d'octrine smile

Il n'y a pas que l'UNION que Doctrine ne gère pas (je ne me souviens plus des autres trucs, ça fait un moment que j'avais vu ça) mais si je dois créer une fonction PHP pour faire chaque chose que Doctrine ne fait pas... C'est plus une perte de temps qu'autre chose. Il me semble qu'il y a certaines fonctionnalités que Doctrine ne prenait pas en compte car c'est spécifique à un certain SGBD (comme par exemple le champ de type ENUM sous MySql), et qu'il est censé pouvoir répercuter ça sur tous les SGBD, on perdrait donc une fonctionnalité de Doctrine (pouvoir changer de SGBD comme on veut).

Splyf a écrit:

Coté php, surment (et encore sa doit pas être très visible). Mais coté mysql?

Coté MySql aussi, j'ai eu certains cas où les requêtes de Doctrine était moins performantes que celles que j'écrivais en natif, faut jamais se fier aux scripts qui font tout tout seul tongue Je pense que Doctrine cherche plus à faire des requêtes génériques qui fonctionnent sur tous les SGBD plutôt que des requêtes performantes, mais ce n'est que mon avis smile
Ma source, bah c'est ma propre expérience de Doctrine wink

Splyf a écrit:

-> et pouf tu a un tableau associatif

Justement je veux un objet pas un tableau, c'est même pour moi tout l'intérêt de Doctrine smile

Après j'avoue que c'est pas mal de pouvoir modifier tous les champs d'une requête à un seul endroit si on renomme les champs dans la base, encore faut-il que ça arrive souvent ^^

Hors ligne

 

#8 31-07-2014 16:49:49

Splyf
Membre
Date d'inscription: 24-10-2013
Messages: 115

Re: QueryBuilder vs NativeQuery & ResultSetMapping

pour le IN ou not IN, c'est exactement comme le UNION, cela revient a écrire plusieurs requête.
C'est dure a faire mais tu peut t'en sortir avec des where, having, join, et les alias dans de très nombreux cas.
(quelqu'un ma même assurez que c'était toujours le cas et il me la montré plusieurs foi, mais c'est un psycopathe xD )

Pour les AST personnalisable, moi je me suis fait un module et n'ai eu qu'a l'écrire qu'une foi et il serra valable probablement jsuqu'a doctrine 3 ^^.

j'ai eu certains cas où les requêtes de Doctrine était moins performantes

Certains cas, donc pas toujours smile  Dans la majorité des cas, le travaille d'optimisation est quand même fortement allégé, même si il est peut être pas optimal a 100%...pour moi le temps de dev et de maintenance compense largement si je doit faire des effort suplémentaire que dans de rare cas smile

De plus, est-ce que le ResultSetMapping te permet de géré toi même le leazy loading des tables jointes (pour le nombre de requêtes)?

par contre si tu veux faire une requête complexe ou spécifique, c'est galère sad

En faite il faut bien pensé en terme de d'entité, et non de table, le dql permet de s'extraire complètement du sgbd. Du coup c'est plus la même logique.
Et Perso je préfère avoir le soutient de mon IDE et de vrai message d'erreur que tout écrire en chaine de caractère et de cherché une erreur de syntaxe via le debugger de mySql, surtout quand on a besoin d'écrire des requête impliquant beaucoup de table et beaucoup de condition.

Quand a la maintenance, c'est tellement plus lisible!

M'enfin bon, moi avant j’écrivais tout le sql a la main et maintenant que j'ai découvert le dql je peut plus m'en passé.
Mais si tu pense être plus performant avec du sql brute, sa serrai dommage de pas le faire, chacun ses expériences  smile

Hors ligne

 

#9 01-08-2014 10:33:19

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: QueryBuilder vs NativeQuery & ResultSetMapping

Seryus a écrit:

Plus performante ne veut pas forcément dire le moins de requêtes possibles wink Et si tu te bases sur ça, j'ai eu des cas où Doctrine me faisait 30 requêtes pour récupérer quelque chose que j'aurais pu avoir en une seule (certes j'avais oublié des jointures et du coup à chaque fois que je faisais un $entity1->getEntity2() il me faisait une requête tongue mais même en ayant ajouté les jointures il ne me l'a pas fait en une seule requête neutral).

Là le problème venait clairement de toi smile. Si tu as bien fais ton DQL (ou via QueryBuilder c'est la même chose) si en SQL ça se fait en une seule requête doctrine le fera aussi en une seule requête. Par défaut il fait du lazyloading donc si tu oublies de faire une jointure ou si tu n'as pas ajouté l'annotation fetch=EAGER sur ta jointure tu auras 2 requêtes. Donc à c'est pas lié à doctrine mais toi qui a oublié des choses wink.

Seryus a écrit:

Il n'y a pas que l'UNION que Doctrine ne gère pas (je ne me souviens plus des autres trucs, ça fait un moment que j'avais vu ça) mais si je dois créer une fonction PHP pour faire chaque chose que Doctrine ne fait pas... C'est plus une perte de temps qu'autre chose. Il me semble qu'il y a certaines fonctionnalités que Doctrine ne prenait pas en compte car c'est spécifique à un certain SGBD (comme par exemple le champ de type ENUM sous MySql), et qu'il est censé pouvoir répercuter ça sur tous les SGBD, on perdrait donc une fonctionnalité de Doctrine (pouvoir changer de SGBD comme on veut).

Comme le dit Splyf tu peux en créer toi même ça fonctionne très bien. Je m'en suis servi notamment pour des fonctions sur les dates. En fait doctrine intègre toutes les fonctions native du SQL tout ce qui est propre à chaque SGBD n'est pas géré. Par exemple MySQL permet de récupérer le mois sur une date via MONTH(date) mais seul MySQL le gère donc c'est à toi d'écrire ta propre fonction qui va transformer le DQL en SQL lorsqu'il rencontre cette instruction. C'est plutôt facile à faire et c'est facilement réutilisable partout smile.

Seryus a écrit:

Coté MySql aussi, j'ai eu certains cas où les requêtes de Doctrine était moins performantes que celles que j'écrivais en natif, faut jamais se fier aux scripts qui font tout tout seul tongue Je pense que Doctrine cherche plus à faire des requêtes génériques qui fonctionnent sur tous les SGBD plutôt que des requêtes performantes, mais ce n'est que mon avis smile
Ma source, bah c'est ma propre expérience de Doctrine wink

Tu as forcément une perte de performance en utilisant doctrine tous les ORM ont ça, ça n'empêche pas d'être utilisé sur des sites à fort trafic smile. Déjà d'une part parce que tu as une transformation du DQL en SQL et d'autre part parce que tu récupères tous les champs des objets (en général, dans le cas contraire faut le spécifier) et enfin tu as la conversation du résultat en objet (Model ou Collection) donc ça prend du temps. Après tu as la possibilité d'utiliser un cache genre memcache qui est très bien géré en natif par doctrine donc tu perds légèrement en performances brut mais une fois en cache tu gagnes en perf et tu sollicites beaucoup moins la bdd donc ça permet à ton application d'avoir globalement des temps de réponse plus rapide.

Un au avantage de doctrine c'est qu'il masque complètement le SQL et il y a pas mal de développeurs qui ne maitrisent pas le SQL ça leur permet d'en faire en utilisant une syntaxe orienté objet sans avoir besoin de connaitre toutes les spécificités d'un SGBD puisque c'est doctrine qui s'occupe d'utiliser la bonne syntaxe en fonction du driver de connexion utilisé smile.
Autre gros avantage d'un ORM c'est lorsque tu souhaites changer de SGBD tu n'as quasiment rien à changer smile.

Hors ligne

 

Pied de page des forums

Propulsé par PunBB
© Copyright 2002–2005 Rickard Andersson
Traduction par punbb.fr

Graphisme réalisé par l'agence Rodolphe Eveilleau
Développement par Kitpages