IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
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

C++ Discussion :

Mapping des objets C++ dans une base de données


Sujet :

C++

  1. #1
    Candidat au Club
    Inscrit en
    Juillet 2008
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Juillet 2008
    Messages : 6
    Points : 2
    Points
    2
    Par défaut Mapping des objets C++ dans une base de données
    Bonjour à tous,

    Tout d'abord désolé si mon message n'est pas situé dans le bon forum, c'est mon premier post...

    Je cherche depuis quelques temps un framework permettant de gérer le mapping Objets / Base de Données Relationnelle. L'équivalent de Hibernate pour Java en quelques sortes.

    Pour vous expliquer mon problème plus en détails, je travaille sur le développement d'une application en C++ utilisant une base de données pour assurer la persistence des entités manipulées. Il semble que les bases de données objets ne font pas le poids par rapport aux bases de données relationnelles, et il faut donc assurer le mapping (ORM).

    Il me semble également que tout faire à la main soit très fastidieux...

    Avez-vous déjà été confrontés à ce type de problème ? Quelles sont vos solutions ?

    Merci

  2. #2
    Expert éminent

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    Oui... mais jamais en C++ directement...

    En C# et en Java, j'utilise Hibernate (ou NHibernate)
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  3. #3
    Candidat au Club
    Inscrit en
    Juillet 2008
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Juillet 2008
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    Merci beaucoup pour ta réponse,

    Et donc en C++, quelle solution me proposerais-tu ?

    J'ai bien pensé à passer par CORBA pour utiliser Java et Hibernate, mais j'ai peur que ça soit un peu lourd pour une simple application où la base de données est stockée localement... Est-ce que je me trompe ?

    D'autant plus que je ne suis absolument pas expert en CORBA et Hibernate...

  4. #4
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Bonjour,
    Je ne connais pas Hibernate donc, je ne sais pas quel est le niveau d'abstraction offert.
    Pour C++, et spécifiquement sous Windows avec Visual et MFC, tu as CRecordSet mais il y a quand même un mapping à faire à la main.

  5. #5
    Membre expérimenté
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 824
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 824
    Points : 1 544
    Points
    1 544
    Par défaut
    J'ai fait ça récemment.

    D'abord, dans tes objets, il faut pouvoir faire de propriétés nommées. Par exemple Client::ville portera le nom de "VILLE".
    Le mieux c'est de faire une interface "IProperty" qui possèdera les méthodes ToString() et FromString(). Puis une classe template CProperty<T> (où T sera un int, un bool ou ce que tu veux).

    Ensuite, j'ai fait un fichier XML pour mapper le nom du champ en base avec le nom du champ dans ma structure de données C++.

    Et enfin, je requête la base, pour chaque enregistrement j'ai le nom des champs, je vais dans le mapping retrouver le nom de la propriété à alimenter, puis j'effectue un FromString sur cette propriété.


    A savoir qu'il te faudra quelques petites astuces comme les classes traits de ce genre :
    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
     
    template<class T> DataTrait
    {
         static const char* CODE = "";
    };
     
    template<> DataTrait<CClient>
    {
         static const char* CODE = "CLIENT";
    };
     
    template<> DataTrait<CCommande>
    {
         static const char* CODE = "COMMANDE";
    };
     
    etc...
    Tu verras aussi que ce n'est pas très judicieux de nommer les propriétés au sein des objets mais plutôt des classes, via les pointeurs de membres sur des propriétés car si tu as 2000 objets à charger par exemple, les nommages vont être duppliqué dans chacun d'entre eux et la mémoire explose.

    Voilà voilà
    "Heureusement qu'il y avait mon nez, sinon je l'aurais pris en pleine gueule" Walter Spanghero

  6. #6
    Candidat au Club
    Inscrit en
    Juillet 2008
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Juillet 2008
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    Merci pour ta réponse !

    Je comprends bien l'idée, mais j'avoue que j'ai du mal à voir précisément comment implémenter tout ça...
    En tout cas, ça confirme bien qu'il n'existe pas de framework correspondant en C++. Il reste donc à tout faire à la main, ou développer soi même ce qui ressemble au framework comme tu le fais.
    Je pense qu'en ce qui me concerne, je vais d'abord faire un mapping manuel, avec l'idée de le faire évoluer à l'avenir vers une solution proche de ce que tu proposes (question de temps...).

  7. #7
    Membre expérimenté
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 824
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 824
    Points : 1 544
    Points
    1 544
    Par défaut
    Bé en fait, je travaille sur un projet liant le C++ et la base de données.

    Le client a rapporté de grosses lenteurs lors du chargement. Aussi, rien que pour connecter la moitié des objets à la base de données, nous étions 3 et ça nous a pris 3 semaines. Et enfin, tu t'aperçois qu'en faisant comme ça, tu charge des clients différemment que des commandes ou des tarifs (en raison des relations avec les autres tables etc...).

    C'est pour ça que je me suis mis à chercher cette solution, plus générique. J'ai mis 1 semaine tout seul à brancher toutes les données...
    "Heureusement qu'il y avait mon nez, sinon je l'aurais pris en pleine gueule" Walter Spanghero

  8. #8
    Candidat au Club
    Inscrit en
    Juillet 2008
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Juillet 2008
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    Effectivement, je suis bien conscient que ça peut être très long à mettre en place...

    J'ai aussi peur qu'en essayant de développer ce que tu me présentes (dont je ne maîtrise pas très bien le principe...), je m'embourbe et que je perde énormément de temps à essayer de faire fonctionner ce framework.

    Quelques précisions sur ta solution :
    - Si j'ai bien compris, tous les membres de mes objets métiers sont des CProtoperty<T> ?
    - Les CProperty héritent de IProperty ?
    - La méthode FromString() renvoie un CProperty ?
    - Les DataTraits ont les mêmes rôles que les CProperty, mais au niveau de classes/tables ?

    Comme quoi je me pose encore beaucoup de questions !

    Par ailleurs, pour éviter d'avoir des temps de chargement de la base trop long, je pense mettre en place un système de "Lazy Loading" (Chargement paresseux), pour ne charger par défaut que les membres qui sont des types de base, et charger à la demande les membres de classes qui sont des types complexes( pointeur vers une autre classe...).
    Et ça non plus, ça ne va pas être simple

  9. #9
    Membre expérimenté
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 824
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 824
    Points : 1 544
    Points
    1 544
    Par défaut
    Oui en fait FromString(const std::string&) et std::string& ToString sont des fonctions virtuelles pures de IProperty. Car ton chargeur de donné (connecté à une base, un fichier txt ou XML) ne manipulera que des IProperty* (il s'en fou que ça soit un booléen ou un int ou autre, c'est pas son soucis, sont rôle est de charger et de passer une valeur sous forme de chaîne de caractère à une propriété. C'est ensuite la propriété qui va se charger de la convertir dans son format.)

    Une propriété ressemble à 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
     
    template<class T>
    class CProperty : public IProperty
    {
        public:
           CProperty(const T& tValue = T());
           const T& GetValue();
           void SetValue(const T&);
     
           void FromString(const std::string& strValue); // Hérité, remplit m_tValue
           std::string ToString(); // Hérité
     
           // opérateur de conversion implicite en T
     
        private:
           T m_tValue;
    };
    Puis tu peux rajouter des mécanismes d'écouteurs etc... selon les besoin futurs


    Les DataTraits te permettent de "nommer" tes classes.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    class CClient
    {
     
    };
     
    const char* DataTrait<CClient>::CODE = "CLIENT";
    Celà te permettra de pouvoir retrouver tes requêtes et ton mapping de données dans les fichiers xml.


    Mais ensuite tu dois gérer les identifiants de tes données (pour ensuite lorsque tu mets à jour ou supprime une donnée en base).
    Il te faudra également des gestionnaires qui stockerons les données chargées et proposeront des fonctions de recherche, de récupération par identifiants, de filtres etc...

    J'ai regroupé quelques classes ci joint pour que tu t'inspires (les trucs "OPS" c'est juste parce que au lieu d'attaquer une base directement on passe par un service installé sur le serveur cible)
    Fichiers attachés Fichiers attachés
    "Heureusement qu'il y avait mon nez, sinon je l'aurais pris en pleine gueule" Walter Spanghero

  10. #10
    Candidat au Club
    Inscrit en
    Juillet 2008
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Juillet 2008
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    Merci beaucoup pour ton aide ! Je vais regarder tout ça de plus près...

  11. #11
    Membre expérimenté
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 824
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 824
    Points : 1 544
    Points
    1 544
    Par défaut
    Avec plaisir
    "Heureusement qu'il y avait mon nez, sinon je l'aurais pris en pleine gueule" Walter Spanghero

  12. #12
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    pourquoi ne pas utiliser le nom de la classe, qu'on peut récupérer via std::type_info::name en pratique ?
    Boost ftw

  13. #13
    Membre expérimenté
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 824
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 824
    Points : 1 544
    Points
    1 544
    Par défaut
    Oui on peut faire ça, mais l'XML du mapping, mes clients pourront l'utiliser pour alimenter une donnée via un autre champ dans la base.

    Donc j'ai préféré lui fournir des balises <CLIENT> que <CCustomer>

    Pour faire ça en fait, j'ai récupéré quelques astuces qu'avait fait ma boite, puis pris le meilleur, selon mes besoins et mon existant, des différents idées trouvés dans les différents articles sur le net
    "Heureusement qu'il y avait mon nez, sinon je l'aurais pris en pleine gueule" Walter Spanghero

  14. #14
    Expert éminent

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    De toute maniere, tu ne peux pas y couper... il te faut un mapping entre la base de données et les champs C++

    Hibernate (et NHibernate) permettent de le faire simplement, juste par utilisation la reflectivité du langage.


    Grosso merdo... soit un table XXXX... tu crées un certain nombre de "mappings"... par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    <mapping table="XXXX" class="MaClasse">
       <id column="COL_ID" type="Long" name="id">
          <generator type="sequence" value="XXXX_SEQ"/>
       </id>
       <property column="NAME" type="String" length="34" name="name"/>
       <property column="TYPE" type="String" length="12" name="type"/>
       <many-to-one class="UneAutreClasse" foreign_column="ID" column="OPTIONS_ID" name="options"/>
    </mapping>
    A partir de ce mapping, on peut générer une classe "data":
    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
    class MaClasse
    {
         long         id;
         string       name;
         string       type;
         UneAutreClasse* options;
     
         long     getId() const
         { return id; }
     
         string   getName() const
         { currentSession().init(this); return name; }
     
         void     setName(string t)
         { name = t; currentSession().modified(this,"name"); }
     
         string   getType() const
         { currentSession().init(this); return type; }
     
         void     setType(string t)
         { type = t; currentSession().modified(this,"type"); }
     
         MonAutreClasse* getOptions() const
         { currentSession().init(this); return options; }
     
         void     setOptions(MonAutreClasse* opt)
         { options = t; currentSession().modified(this,"options"); }
    };
    Ainsi l'objet peut avoir plusieurs états dans une session:
    - Détaché (inconnu). init() ne fait rien. save() va lui assigner un identifiant, et le marquer "Chargé" et "created".
    - Identifié (on ne connait que sont identifiant, c'est l'état par défaut quand on initialise un objet externe comme "MonAutreClasse", pour éviter de multiples queries à la DB). init() va la charger (en ne touchant que les propriétés non modifiées), et save() ne fait rien.
    - Chargé (on connait tout de lui). init() et save() ne font rien.

    La session peut être 'flushé', auquel cas, tous les objets "created" vont être créés, et tous les objets "modifiés" vont êter mis à jour.


    Bien sur, hibernate va beaucoup plus loin (la reflection du langage permettant de faire pratiquement tout, entre les intercepteurs sur certains objets, et autres). Mais rien n'empeche d'en copier les stratégies principales en C++.
    Par contre, il faut un passage Mapping -> classes C++ (donc génération de code).

    A noter qu'on peut "déduire" le mapping de la DB...
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  15. #15
    Membre expérimenté
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 824
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 824
    Points : 1 544
    Points
    1 544
    Par défaut
    Je vais aller voir un peu la doc d'Hibernate, même si j'en ai pas besoin, c'est pour pas mourir con


    Sinon pour requêter sur la base de données, est-ce qu'il y a une librairie qui permette de le faire ? J'ai vu que Oracle proposait une petite librairie en C++, mais existe-t-il la même chose pour SQLServer ?
    Ou mieux, y a-t-il une librairie gérant tout type de base ?


    Merci,

    A bientôt
    "Heureusement qu'il y avait mon nez, sinon je l'aurais pris en pleine gueule" Walter Spanghero

  16. #16
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    Citation Envoyé par mister3957 Voir le message
    Sinon pour requêter sur la base de données, est-ce qu'il y a une librairie qui permette de le faire ? J'ai vu que Oracle proposait une petite librairie en C++, mais existe-t-il la même chose pour SQLServer ?
    Ou mieux, y a-t-il une librairie gérant tout type de base ?
    J'aime bien ODBC, c'est l'API de base Microsoft (si tu es sur une plateforme Microsoft) et c'est indépendant de la base de données (Oracle, SQL Server, MySQL, ...) pour peu que tu aies les drivers ODBC de la base de données que tu utilises.
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  17. #17
    Membre expérimenté
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 824
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 824
    Points : 1 544
    Points
    1 544
    Par défaut
    Ouais je préfère éviter ODBC...

    Je pense que j'vais réfléchir un peu plus et me faire une interface de manipulation de BDD puis encapsuler l'implémentation dans des DLL (une pour chaque type de base et même pour fichier plat, xml etc...)


    Merci
    "Heureusement qu'il y avait mon nez, sinon je l'aurais pris en pleine gueule" Walter Spanghero

  18. #18
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    ODBC n'a rien à voir avec Microsoft, c'est une API standard. Microsoft n'en fournit qu'une implémentation.
    Boost ftw

  19. #19
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    Citation Envoyé par loufoque Voir le message
    ODBC n'a rien à voir avec Microsoft, c'est une API standard. Microsoft n'en fournit qu'une implémentation.
    C'est vrai, je me suis emporté, j'ai oublié qu'il existait d'autres implémentations sur d'autres OS.
    A ma décharge, ODBC a été poussé dès le début par Microsoft et c'est Microsoft qui a fournit la première implémentation.
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

Discussions similaires

  1. Insertion des contenus gtkentry dans une base de données
    Par charles9 dans le forum GTK+ avec C & C++
    Réponses: 2
    Dernier message: 02/06/2008, 18h13
  2. Liste des tables existantes dans une base de données
    Par Lorenzole+bo dans le forum VBA Access
    Réponses: 1
    Dernier message: 13/11/2007, 20h15
  3. [Conception] Stocker des fichiers multimédia dans une base de données
    Par haifa84 dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 11/03/2006, 17h47
  4. Intégration des fichier XML dans une base de données MySQL
    Par bebemoundjou dans le forum XQUERY/SGBD
    Réponses: 8
    Dernier message: 25/11/2005, 22h41
  5. Recuperation des objet ole dans une base SQL
    Par TOPGUN89 dans le forum MS SQL Server
    Réponses: 7
    Dernier message: 25/11/2005, 09h14

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo