- 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

