Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

  1. #1
    Membre du Club
    [QxOrm 1.2.2] Génération d'identifiants pour insertion dans une collection
    Hello !

    Petite question: comment faire pour générer l'id (long auto-incrementé) de la classe ORM Toto pour l'insert dans une QxCollection<long, Toto : : Ptr> ?

    (je sais pas si je suis très clair)...

    Merci par avance !

  2. #2
    Expert confirmé
    je sais pas si je suis très clair
    => j'avoue que je comprends pas trop la question

    Un ID est généré pendant l'appel à la fonction qx::dao::insert.
    A noter : la fonction qx::dao::insert peut prendre en paramètre une instance, un pointeur vers une instance, ou bien une collection d'objets (je ne sais pas si ça répond à ta question).
    Le site de la bibliothèque QxOrm : bibliothèque C++ de gestion de données (Mapping Objet Relationnel ou ORM) basée sur les frameworks Qt et boost.
    QxEntityEditor : éditeur graphique pour la bibliothèque QxOrm (application multi-plateforme pour gérer graphiquement le modèle d'entités).

    Tutoriel : installer un environnement de développement avec QxOrm sous Windows.
    Tutoriel qxBlog : gestion de blogs en C++/Qt.
    Tutoriel qxClientServer : création d'un serveur d'applications en C++/Qt.

  3. #3
    Membre du Club
    Note: Je suis en train de me rendre compte que je n'ai peut être pas bien compris la notion de relation. Voir autre post que je vais écrire plus tard.

    Ok, donc désolé, je ré-explique:
    J'ai créé une table Form comme ceci:

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    class Form
    {
    public:
    // -- typedef
        typedef Form This;
        typedef boost::shared_ptr<This> Ptr;
        typedef qx::QxCollection<long, FormPage:<img src="images/smilies/icon_razz.gif" border="0" alt="" title=":P" class="inlineimg" />tr> ListPageT;
     
    public:
        Form() {}
        virtual ~Form() {}
     
    public:
        long id;
        QString name;
        ListPageT pages;
    };


    Le formulaire est composé de pages (je ne donne pas le code de FormPage car c'est basique, disons que c'est une classe qui ressemble à Form.

    On veut maintenant créer un formulaire avec des pages.
    Du coup, j'insère mes éléments comme ceci:
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    Form:<img src="images/smilies/icon_razz.gif" border="0" alt="" title=":P" class="inlineimg" />tr formToORM( const core::form::Form & formDoc )
    {
        Form:<img src="images/smilies/icon_razz.gif" border="0" alt="" title=":P" class="inlineimg" />tr dbForm( new Form() );
        {
            using namespace core;
            dbForm->name = formDoc.name().c_str();
            BOOST_FOREACH( const form::FormPage & page, formDoc.pages() )
            {
                FormPage:<img src="images/smilies/icon_razz.gif" border="0" alt="" title=":P" class="inlineimg" />tr dbFormPage = formPageToORM( page );
                dbForm->pages.insert( dbFormPage->id, dbFormPage );
            }
        }
        return dbForm;
    }


    Le problème qui se pose est que je n'ai pas l'id avant qu'il ne soit inséré dans la bdd à l'appel de cette fonction:
    dbForm->pages.insert( dbFormPage->id, dbFormPage );

    En fait, je crois que je n'ai pas bien compris: l'insert d'une collection prend un id (premier paramètre de la template) qui ne représente pas du tout l'id de l'enregistrement de la relation dans la BDD, c'est ça ? Je crois que je confonds les deux tout simplement !

  4. #4
    Expert confirmé
    En fait, je crois que je n'ai pas bien compris: l'insert d'une collection prend un id (premier paramètre de la template) qui ne représente pas du tout l'id de l'enregistrement de la relation dans la BDD, c'est ça ? Je crois que je confonds les deux tout simplement !
    Oui tu confonds je pense : qx::QxCollection n'a absolument rien à voir avec la notion de relation dans QxOrm !
    Il faut que tu vois la classe qx::QxCollection comme un conteneur classique, du même style que std::vector, QList ou boost::unordered_map.
    Pour plus de détails sur ce nouveau conteneur, il y a une explication dans la FAQ : Pourquoi QxOrm fournit un nouveau type de container qx::QxCollection<Key, Value> ?
    Si ce n'est toujours pas clair malgré l'explication de la FAQ => n'hésite pas à me redemander...

    Donc, le 1er élément du template qx::QxCollection est une clé (pour accéder rapidement à la valeur associée), pas forcément un ID provenant d'une BDD (c'est une hash_table en fait).
    Dans le cas d'un élément provenant d'une BDD, ça parait logique de mettre comme clé son ID (mais ce n'est pas une obligation).

    Concernant ton code, de ce que je comprends, tu as une structure FormA et PageA que tu souhaites convertir en FormB et PageB en utilisant les méthodes formToORM() et formPageToORM().
    Je vois 2 solutions à ta problématique :
    1- soit tu décides d'utiliser un autre conteneur car tu ne connais pas de clé au moment de l'appel à formPageToORM() (car ton objet n'est pas encore en BDD) => à ce moment là, tu peux utiliser une QList<FormPage:: Ptr> par exemple.
    2- soit tu continues à utiliser qx::QxCollection et c'est à toi de définir une clé au moment de l'insertion dans la collection. Tu peux utiliser la logique suivante dans ton code : si ma page n'existe pas encore en BDD, j'utilise une clé négative. Ce qui donnerait quelque chose comme ça :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    Form:<img src="images/smilies/icon_razz.gif" border="0" alt="" title=":P" class="inlineimg" />tr formToORM( const core::form::Form & formDoc )
    {
        Form:<img src="images/smilies/icon_razz.gif" border="0" alt="" title=":P" class="inlineimg" />tr dbForm( new Form() );
        {
            using namespace core;
            dbForm->name = formDoc.name().c_str();
            long lKey = 0;
            BOOST_FOREACH( const form::FormPage & page, formDoc.pages() )
            {
                FormPage:<img src="images/smilies/icon_razz.gif" border="0" alt="" title=":P" class="inlineimg" />tr dbFormPage = formPageToORM( page );
                if (page->id != 0) { lKey = page->id; }
                else { lKey--; }
                dbForm->pages.insert( lKey, dbFormPage );
            }
        }
        return dbForm;
    }

    Ensuite, au moment de faire la sauvegarde en BDD, tu testes la clé :
    - si clé positive => je fais un update
    - si clé négative => je fais un insert

    EDIT : Pense à la méthode reserve() pour optimiser un peu ton code
    Le site de la bibliothèque QxOrm : bibliothèque C++ de gestion de données (Mapping Objet Relationnel ou ORM) basée sur les frameworks Qt et boost.
    QxEntityEditor : éditeur graphique pour la bibliothèque QxOrm (application multi-plateforme pour gérer graphiquement le modèle d'entités).

    Tutoriel : installer un environnement de développement avec QxOrm sous Windows.
    Tutoriel qxBlog : gestion de blogs en C++/Qt.
    Tutoriel qxClientServer : création d'un serveur d'applications en C++/Qt.

  5. #5
    Membre du Club
    Ah ok d'accord, je vois !

    Merci pour toutes ces explications.
    En fait, je croyais que quand j'allais faire l'insert de ma classe Form avec qx::dao::insert, ça allait enregistrer toutes les relations (donc également les pages qui sont dans la collection).

    Je vais voir comment je peux faire du coup
    Merci !

  6. #6
    Expert confirmé
    je croyais que quand j'allais faire l'insert de ma classe Form avec qx::dao::insert, ça allait enregistrer toutes les relations
    C'est le même principe que pour le fetch :
    * qx::dao::insert : ne va insérer que dans 1 seule table ;
    * qx::dao::insert_with_relation : va insérer dans plusieurs tables.
    Le site de la bibliothèque QxOrm : bibliothèque C++ de gestion de données (Mapping Objet Relationnel ou ORM) basée sur les frameworks Qt et boost.
    QxEntityEditor : éditeur graphique pour la bibliothèque QxOrm (application multi-plateforme pour gérer graphiquement le modèle d'entités).

    Tutoriel : installer un environnement de développement avec QxOrm sous Windows.
    Tutoriel qxBlog : gestion de blogs en C++/Qt.
    Tutoriel qxClientServer : création d'un serveur d'applications en C++/Qt.

  7. #7
    Candidat au Club
    Bonjour, Bonsoir

    Je me permets juste de ré-ouvrir cette discussion pour avoir des quelques précisions concernant la fonction insert_with_relation.
    (Je sens que je vais la refermer aussitôt tellement la question est simple, et pourtant je coince)

    J'ai quatre tables.
    La première appelé table1 a une relation oneToMany avec la deuxième table appelé table2
    table2 a aussi une relation oneToMany avec la troisième table appelé table3.
    Enfin table3 a une relation oneToMany avec la quatrième table appelé table4.

    Les cléfs primaires sont respectivement table1_id, table2_id, table3_id et table4_id.

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    table1_ptr tab1; tab1.reset(new table1());
    table2_ptr tab2; tab2.reset(new table2());
    table3_ptr tab3; tab3.reset(new table3());
    table4_ptr tab4; tab4.reset(new table4());
     
    // On rentre les informations relatives á chaque table....
     
    // On linke tout ceci
    tab4->m_tab3 = tab3;
    tab3->m_tab2 = tab2;
    tab2->m_tab1 = tab1
     
    // J'essaye maintenant d'inserer la table4 avec les relations définies au dessus
    QStringList relations = QStringList() << "table3_id->table2_id->table1_id";
    // J'ai également essayer avec *->*->*
    qx::dao::insert_with_relation(relations, tab4);
     
    // Resultat:
    table4 et table3 ont été correctement remplis. table2 et table1 sont vides


    En gros ma question est simple, la fonction insert_with_relation fonctionne t'elle sur trois niveaux de relations? Et si oui qu'elle serait la marche à suivre?

    Sinon, bah je trouve toujours QxOrM super cool!

    Bonne soirée

  8. #8
    Expert confirmé
    En gros ma question est simple, la fonction insert_with_relation fonctionne t'elle sur trois niveaux de relations?
    Non, juste 1 seul niveau de relation.

    Si tu veux mettre à jour plusieurs niveaux de relations d'un seul coup, il faut utiliser la fonction suivante : qx::dao::save_with_relation_recursive().
    Plusieurs possibilités pour utiliser cette fonction (voir le 2ème paramètre de cette fonction) :
    • qx::dao::save_mode::e_check_insert_or_update : valeur par défaut mais plutôt lent car doit vérifier chaque élément pour savoir si c'est une insertion ou une mise à jour ;
    • qx::dao::save_mode::e_insert_only : très rapide si tu sais que tu insères un élément et toutes ses relations d'un coup (insertion en mode batch) ;
    • qx::dao::save_mode::e_update_only : très rapide si tu sais que tu mets à jour un élément et toutes ses relations d'un coup (mise à jour en mode batch).


    Remarque : si tu travailles beaucoup avec les relations, je te conseille d'activer l'option suivante :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    qx::QxSqlDatabase::getSingleton()->setForceParentIdToAllChildren(true);

    Cette fonction gère automatiquement les identifiants de tes relations.
    Le site de la bibliothèque QxOrm : bibliothèque C++ de gestion de données (Mapping Objet Relationnel ou ORM) basée sur les frameworks Qt et boost.
    QxEntityEditor : éditeur graphique pour la bibliothèque QxOrm (application multi-plateforme pour gérer graphiquement le modèle d'entités).

    Tutoriel : installer un environnement de développement avec QxOrm sous Windows.
    Tutoriel qxBlog : gestion de blogs en C++/Qt.
    Tutoriel qxClientServer : création d'un serveur d'applications en C++/Qt.