- 1
[Opened] jDao et problème de jointure sur clé étrangère
Posted by PomCompot on 04/02/2009 16:47
Bonjour,
Je rencontre un problème lié aux DAO et à mon modèle relationnel. En effet, je désire faire une requête sur une entité ayant une relation réflexive sur elle-même (lien de parenté). J'ai donc la relation suivante sur l'entité Noeud :
---------- | | 0,n | Noeud 0,1 --
Cette entité a par ailleurs des clés étangères provenant de différentes entités. Voici sa déclaration de DAO :
<datasources> <primarytable name="noeud" realname="noeud" primarykey="ID_NOEUD,NUM_VERSION" /> <foreigntable name="classe" realname="classe" primarykey="ID_CLASSE" onforeignkey="ID_CLASSE" /> <optionalforeigntable name="foreignNoeud1" realname="noeud" primarykey="ID_NOEUD" onforeignkey="ID_NOEUD_PARENT" /> <optionalforeigntable name="foreignNoeud2" realname="noeud" primarykey="NUM_VERSION" onforeignkey="NUM_VERSION_PARENT" /> </datasources> <record> <property name="idNoeud" fieldname="ID_NOEUD" datatype="autoincrement"/> <property name="numVersion" fieldname="NUM_VERSION" datatype="numeric" required="true"/> <property name="idClasse" fieldname="ID_CLASSE" datatype="int" required="true"/> <property name="idNoeudParent" fieldname="ID_NOEUD_PARENT" datatype="int" default=""/> <property name="numVersionParent" fieldname="NUM_VERSION_PARENT" datatype="numeric" default=""/> <property name="numOrdreNoeud" fieldname="NUM_ORDRE_NOEUD" datatype="int" default=""/> <property name="nomClasse" fieldname="NOM_CLASSE" datatype="string" default="" maxlength="25"/> </record>
Voici la requête générée :
SELECT `noeud`.`ID_NOEUD` as `idNoeud`, `noeud`.`NUM_VERSION` as `numVersion`, `noeud`.`ID_CLASSE` as `idClasse`, `noeud`.`ID_NOEUD_PARENT` as `idNoeudParent`, `noeud`.`NUM_VERSION_PARENT` as `numVersionParent`, `noeud`.`NUM_ORDRE_NOEUD` as `numOrdreNoeud`, `noeud`.`NOM_CLASSE` as `nomClasse` FROM `noeud` AS `noeud` LEFT JOIN `noeud` AS `foreignNoeud1` ON ( `noeud`.`ID_NOEUD_PARENT`=`foreignNoeud1`.`ID_NOEUD`) LEFT JOIN `noeud` AS `foreignNoeud2` ON ( `noeud`.`NUM_VERSION_PARENT`=`foreignNoeud2`.`NUM_VERSION`), `classe` AS `classe` WHERE `noeud`.`ID_CLASSE`=`classe`.`ID_CLASSE` AND `noeud`.`ID_NOEUD_PARENT` =10 AND `noeud`.`NUM_VERSION_PARENT` =1
J'ai tenté de la généré et grâce à des conditions via un service comme suit :
$conditions = jDao::createConditions(); $conditions->addCondition('idNoeudParent', '=', $idNoeudParent); $conditions->addCondition('numVersionParent', '=', $numVersionParent); $liste = $factory->findBy($conditions);
et via une déclaration XML :
<method name="findEnfantsByPk" type="select"> <parameter name="idNoeudParent"/> <parameter name="numVersionParent"/> <conditions> <eq property="idNoeudParent" expr="$idNoeudParent" /> <eq property="numVersionParent" expr="$numVersionParent" /> </conditions> </method>
Même résultat pour les deux déclarations. Beaucoup trop de résultats sont envoyés.
Je ne souhaiterai finalement que cette requête-ci :
SELECT noeud.ID_NOEUD FROM noeud WHERE noeud.ID_NOEUD_PARENT=10 AND noeud.NUM_VERSION_PARENT=1;
Ai-je loupé quelque chose ou les DAO ne me permettent pas d'avoir cela automatiquement avec une relation réflexive et des clés étrangères ?
Merci beaucoup à ceux qui voudront bien se pencher sur ce problème pas forcément simple.
PomCompot
[Opened] Re: jDao et problème de jointure sur clé étrangère
Posted by PomCompot on 04/02/2009 17:16
J'ai bien trouvé la solution d'ajouter une clause distinct à la définition XML de la requête :
<method name="findEnfantsByPk" type="select" distinct="true">
Néanmoins, cela n'est qu'un contournement du problème puisque la requête n'est pas pour autant optimisée.
[Opened] Re: jDao et problème de jointure sur clé étrangère
Posted by laurentj on 04/02/2009 17:19
Déjà, tu as déclaré deux jointures, une sur chaque champs de la clé primaire. Ça ne va pas, même d'un point de vue sql. Une jointure sur une clé à champs multiple, ça se fait sur l'ensemble de ces champs. Il aurait fallu faire :
<datasources> <primarytable name="noeud" realname="noeud" primarykey="ID_NOEUD,NUM_VERSION" /> <foreigntable name="classe" realname="classe" primarykey="ID_CLASSE" onforeignkey="ID_CLASSE" /> <optionalforeigntable name="foreignNoeud" realname="noeud" primarykey="ID_NOEUD,NUM_VERSION" onforeignkey="ID_NOEUD_PARENT, NUM_VERSION_PARENT" /> </datasources>
Ensuite, tu dis que ça te ramène trop de résultat (forcément à cause de la double jointure fausse...), et tu montre à la fin que tu veux faire une requête, qui en fin de compte est toute simple, sans jointure. Pourquoi indiques tu alors une jointure dans la description de l'objet ?
Si tu ne veux pas faire de jointure, n'indique pas de jointure, et finalement, ton dao serait tout bête :
<datasources> <primarytable name="noeud" realname="noeud" primarykey="ID_NOEUD,NUM_VERSION" /> </datasources> <record> <property name="idNoeud" fieldname="ID_NOEUD" datatype="autoincrement"/> <property name="numVersion" fieldname="NUM_VERSION" datatype="numeric" required="true"/> <property name="idClasse" fieldname="ID_CLASSE" datatype="int" required="true"/> <property name="idNoeudParent" fieldname="ID_NOEUD_PARENT" datatype="int" default=""/> <property name="numVersionParent" fieldname="NUM_VERSION_PARENT" datatype="numeric" default=""/> <property name="numOrdreNoeud" fieldname="NUM_ORDRE_NOEUD" datatype="int" default=""/> <property name="nomClasse" fieldname="NOM_CLASSE" datatype="string" default="" maxlength="25"/> </record> <factory> <method name="findEnfantsByPk" type="select"> <parameter name="idNoeudParent"/> <parameter name="numVersionParent"/> <conditions> <eq property="idNoeudParent" expr="$idNoeudParent" /> <eq property="numVersionParent" expr="$numVersionParent" /> </conditions> </method> </factory>
Enfin, tu as indiqué une jointure sur la table "classe". Elle est inutile vu que tu ne mappes aucune propriété sur ses champs.
[Opened] Re: jDao et problème de jointure sur clé étrangère
Posted by PomCompot on 04/03/2009 11:09
Ok. jDao reste donc très bien adapté aux problèmes simples. Je vais donc peser pour chacun de mes problèmes le pour et le contre de l'utilisation des DAO par rapport à jDb.
Merci pour ton aide.
- 1