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 !
Version imprimable
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 !
:koi: => j'avoue que je comprends pas trop la question :mrgreen:Citation:
je sais pas si je suis très clair
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).
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:
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.Code:
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::Ptr> ListPageT; public: Form() {} virtual ~Form() {} public: long id; QString name; ListPageT pages; };
On veut maintenant créer un formulaire avec des pages.
Du coup, j'insère mes éléments comme ceci:
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:Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 Form::Ptr formToORM( const core::form::Form & formDoc ) { Form::Ptr dbForm( new Form() ); { using namespace core; dbForm->name = formDoc.name().c_str(); BOOST_FOREACH( const form::FormPage & page, formDoc.pages() ) { FormPage::Ptr dbFormPage = formPageToORM( page ); dbForm->pages.insert( dbFormPage->id, dbFormPage ); } } return dbForm; }
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 !
Oui tu confonds je pense : qx::QxCollection n'a absolument rien à voir avec la notion de relation dans QxOrm !Citation:
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 !
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 :
Ensuite, au moment de faire la sauvegarde en BDD, tu testes la clé :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 Form::Ptr formToORM( const core::form::Form & formDoc ) { Form::Ptr dbForm( new Form() ); { using namespace core; dbForm->name = formDoc.name().c_str(); long lKey = 0; BOOST_FOREACH( const form::FormPage & page, formDoc.pages() ) { FormPage::Ptr dbFormPage = formPageToORM( page ); if (page->id != 0) { lKey = page->id; } else { lKey--; } dbForm->pages.insert( lKey, dbFormPage ); } } return dbForm; }
- 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 ;)
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 !
C'est le même principe que pour le fetch :Citation:
je croyais que quand j'allais faire l'insert de ma classe Form avec qx::dao::insert, ça allait enregistrer toutes les relations
* qx::dao::insert : ne va insérer que dans 1 seule table ;
* qx::dao::insert_with_relation : va insérer dans plusieurs tables.
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) :roll:
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.
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?Code:
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
Sinon, bah je trouve toujours QxOrM super cool!;)
Bonne soirée
Non, juste 1 seul niveau de relation.Citation:
En gros ma question est simple, la fonction insert_with_relation fonctionne t'elle sur trois niveaux de relations?
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 :
Cette fonction gère automatiquement les identifiants de tes relations.Code:qx::QxSqlDatabase::getSingleton()->setForceParentIdToAllChildren(true);