Quick links: Content - sections - sub sections
EN FR
Quick Search Advanced search
 
Page

  [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

Reply #1 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

Reply #2 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

Reply #3 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.

 
Page
  1. jDao et problème de jointure sur clé étrangère