QxOrm C++

Home Download Quick sample Tutorial Faq Link

QxOrm >> Faq Version courante : QxOrm 1.1.2 (LGPL) Version française du site Web site english version

Qu'est-ce que QxOrm ?

QxOrm est une librairie C++ de gestion de données développée par Lionel Marty, Ingénieur en développement logiciel depuis 7 ans.
QxOrm fournit de nombreuses fonctionnalités à partir d'une simple fonction de paramétrage :
  • persistance : communication avec de nombreuses bases de données (avec support des relations 1-1, 1-n, n-1 et n-n)
  • serialization des données (flux binaire et xml)
  • moteur de reflection pour accéder aux classes, attributs et invoquer des méthodes

Comment contacter QxOrm pour indiquer un bug ou poser une question ?

Si vous trouvez un bug ou si vous avez une question concernant le fonctionnement de la librairie QxOrm, vous pouvez envoyer un mail à : support@qxorm.com.
QxOrm est également disponible sur le site SourceForge : plate-forme d'hébergement de projets de développements de logiciels libres.
Un forum dédié à QxOrm est disponible en cliquant ici.


Quelles sont les bases de données prises en compte par QxOrm ?

QxOrm utilise le moteur QtSql de Qt basé sur un système de plugin.
Une liste détaillée des bases de données supportées est disponible sur le site de Qt en cliquant ici.
Le plugin ODBC (QODBC) assure une compatibilité avec de nombreuses bases de données.
Pour des performances optimales, il est possible d'utiliser un plugin spécifique à une base de données :
  • QMYSQL : MySQL
  • QPSQL : PostgreSQL (versions 7.3 and above)
  • QOCI : Oracle Call Interface Driver
  • QSQLITE : SQLite version 3
  • QDB2 : IBM DB2 (version 7.1 and above)
  • QIBASE : Borland InterBase
  • QTDS : Sybase Adaptive Server

Pourquoi QxOrm est dépendant de 2 librairies : boost et Qt ?

QxOrm utilise de nombreuses fonctionnalités disponibles dans les excellentes librairies boost et Qt.
De plus, ces 2 librairies sont utilisées dans de nombreux projets à la fois professionnels et open-source.
Il existe un grand nombre de forums, de tutoriaux, et toute une communauté pour répondre à toutes les problématiques que vous pourriez rencontrer.
L'objectif de QxOrm n'est pas de redévelopper des fonctionnalités qui existent déjà mais de fournir un outil performant d'accès aux bases de données comme il en existe dans d'autres langages (Java avec Hibernate, .Net avec NHibernate, Ruby, Python, etc...).

boost boost : de nombreux modules de la librairie boost font partie de la nouvelle norme C++.
C'est une librairie reconnue pour sa qualité, son code 'C++ moderne', sa documentation, sa portabilité, etc...
QxOrm utilise les fonctionnalités suivantes de boost : smart_pointer, serialization, type_traits, multi_index_container, unordered_container, any, tuple, foreach, function.
Il est conseillé d'installer et d'utiliser la dernière version de boost disponible à l'adresse suivante : http://www.boost.org/

Qt Qt : bibliothèque complète : IHM (QtGui), réseau (QtNetwork), XML (QtXml), base de données (QtSql), etc...
La documentation est excellente et le code C++ écrit à partir de cette bibliothèque est à la fois performant et simple de compréhension.
Depuis le rachat par Nokia et sa nouvelle licence LGPL, Qt est sans contexte la bibliothèque phare du moment.
QxOrm est compatible avec les principaux objets définis par Qt : QObject, QString, QDate, QTime, QDateTime, QList, QHash, QSharedPointer, QScopedPointer, etc...
Il est conseillé d'installer et d'utiliser la dernière version de Qt disponible à l'adresse suivante : http://qt.nokia.com/


Pourquoi QxOrm nécessite un en-tête précompilé (precompiled header) pour pouvoir être utilisé ?

QxOrm utilise les techniques de méta-programmation C++ pour fournir une grande partie de ses fonctionnalités.
Vous n'avez pas besoin de savoir utiliser la méta-programmation pour travailler avec la librairie QxOrm.
En effet, QxOrm se veut simple d'utilisation et un code C++ écrit avec Qt et QxOrm est facile à lire, donc facile à développer et à maintenir.

Cependant, la méta-programmation est couteuse en temps de compilation.
En utilisant un fichier precompiled.h, votre projet se compilera beaucoup plus vite.
Un autre avantage (et non des moindres) est que le fichier QxOrm.h regroupe les fonctionnalités de base des librairies boost et Qt.
Il n'est donc plus nécessaire d'écrire #include <QtCore/QString.h> pour utiliser la classe QString de Qt par exemple.
De même, pour utiliser les pointeurs intelligents de boost, il n'est plus nécessaire d'écrire #include <boost/shared_ptr.hpp>.


Est-il possible d'accélérer les temps de compilation de mon projet ?

Oui, si la serialization de vos données au format xml n'est pas utilisée dans votre projet, vous pouvez désactiver cette fonctionnalité.
Les temps de compilation seront alors réduits mais vous n'aurez plus accès au namespace qx::serialization:xml.
Pour désactiver la serialization xml, il faut ouvrir le fichier QxConfig.h et modifier la constante _QX_SERIALIZE_XML.
Une recompilation de la librairie QxOrm est nécessaire pour prendre en compte cette modification.

Une autre possibilité est d'utiliser les classes polymorphiques de la librairie boost::serialization (à la place des classes template).
Cette fonctionnalité réduit les temps de compilation ainsi que la taille de l'éxecutable généré.
En contre-partie, la vitesse d'exécution de votre programme sera réduite puisqu'une partie du travail effectué lors de la compilation devra être réalisé à l'exécution de votre application.
Pour activer cette fonctionnalité dans QxOrm, vous devez modifier la constante _QX_SERIALIZE_POLYMORPHIC du fichier QxConfig.h.
Attention : les fonctions de serialization seront alors accessibles depuis les namespace suivants : qx::serialization::polymorphic_binary, qx::serialization::polymorphic_text et qx::serialization::polymorphic_xml.
Une recompilation de la librairie QxOrm est nécessaire pour prendre en compte cette modification.


Pourquoi QxOrm fournit un nouveau type de container qx::QxCollection<Key, Value> ?

Il existe de nombreux container dans les librairies stl, boost et Qt.
Il est donc légitime de se poser cette question : à quoi sert qx::QxCollection<Key, Value> ?
qx::QxCollection<Key, Value> est un nouveau container (basé sur l'excellente librairie boost::multi_index_container) qui possède les fonctionnalités suivantes :
  • conserve l'ordre d'insertion des éléments dans la liste
  • accès rapide à un élément par son index : équivaut à std::vector<T> ou QList<T> par exemple
  • accès rapide à un élément par une clé (hash-map) : équivaut à QHash<Key, Value> ou boost::unordered_map<Key, Value> par exemple
  • fonctions de tri sur le type Key et sur le type Value
Remarque : qx::QxCollection<Key, Value> est compatible avec la macro foreach fournie par la librairie Qt ainsi que par la macro BOOST_FOREACH fournie par la librairie boost.
Cependant, chaque élément renvoyé par ces 2 macros correspond à un objet de type std::pair<Key, Value>.
Pour obtenir un résultat 'plus naturel' et plus lisible, il est conseillé d'utiliser la macro _foreach : cette macro utilise BOOST_FOREACH pour tous les container sauf pour qx::QxCollection<Key, Value>.
Dans ce cas, l'élément renvoyé correspond au type Value (voir par la suite l'exemple d'utilisation).
La macro _foreach est donc compatible avec tous les container (stl, Qt, boost, etc...) puisqu'elle utilise la macro BOOST_FOREACH.

Autre Remarque : qx::QxCollection<Key, Value> est particulièrement adapté pour recevoir des données issues d'une base de données.
En effet, ces données peuvent être triées (en utilisant ORDER BY dans une requête sql par exemple), il est donc important de conserver l'ordre d'insertion des éléments dans la liste.
De plus, chaque donnée issue d'une base de données possède un identifiant unique. Il est donc intéressant de pouvoir accéder à un élément en fonction de cet identifiant unique de manière extrèmement rapide (hash-map).

Exemple d'utilisation :
/* definition of drug class with 3 properties : code, name, description */
class drug { public: QString code; QString name; QString desc; };

/* smart pointer of drug */
typedef boost::shared_ptr<drug> drug_ptr;

/* collection of drugs by code */
qx::QxCollection<QString, drug_ptr> lstDrugs;

/* create 3 new drugs */
drug_ptr d1; d1.reset(new drug()); d1->code = "code1"; d1->name = "name1"; d1->desc = "desc1";
drug_ptr d2; d2.reset(new drug()); d2->code = "code2"; d2->name = "name2"; d2->desc = "desc2";
drug_ptr d3; d3.reset(new drug()); d3->code = "code3"; d3->name = "name3"; d3->desc = "desc3";

/* insert drugs into the collection */
lstDrugs.insert(d1->code, d1);
lstDrugs.insert(d2->code, d2);
lstDrugs.insert(d3->code, d3);

/* iterate with '_foreach' keyword */
_foreach(drug_ptr p, lstDrugs)
{ qDebug() << qPrintable(p->name) << " " << qPrintable(p->desc); }

/* iterate with 'for' keyword */
for (long l = 0; l < lstDrugs.count(); ++l)
{
   drug_ptr p = lstDrugs.getByIndex(l);
   QString code = lstDrugs.getKeyByIndex(l);
   qDebug() << qPrintable(p->name) << " " << qPrintable(p->desc);
}

/* iterate with 'QxCollectionIterator' java style */
qx::QxCollectionIterator<QString, drug_ptr> itr(lstDrugs);
while (itr.next())
{
   QString code = itr.key();
   qDebug() << qPrintable(itr.value()->name) << " " << qPrintable(itr.value()->desc);
}

/* sort ascending by key and sort descending by value */
lstDrugs.sortByKey(true);
lstDrugs.sortByValue(false);

/* access drug by code */
drug_ptr p = lstDrugs.getByKey("code2");

/* access drug by index */
drug_ptr p = lstDrugs.getByIndex(2);

/* test if drug exists and if collection is empty */
bool bExist = lstDrugs.exist("code3");
bool bEmpty = lstDrugs.empty();

/* remove the second drug from collection */
lstDrugs.removeByIndex(2);

/* remove the drug with "code3" */
lstDrugs.removeByKey("code3");

/* clear the collection */
lstDrugs.clear();


Faut-il utiliser QString ou std::string ?

QxOrm conseille d'utiliser la classe QString pour la gestion des chaînes de caractères.
Même si boost fournit de nombreuses fonctionnalités avec son module boost::string_algo, la classe QString est plus simple à utiliser et surtout prend en charge automatiquement les différents formats : Ascii, Utf8, Utf16, etc...
Cependant, QxOrm est compatible avec std::string et std::wstring si vous préférez utiliser ce type de chaîne de caractères.


Faut-il utiliser les pointeurs intelligents smart-pointer ?

QxOrm conseille fortement d'utiliser les pointeurs intelligents de boost ou Qt.
Le langage C++ ne possède pas de Garbage Collector comme Java ou C# par exemple.
L'utilisation des smart-pointer simplifie énormément la gestion de la mémoire en C++.
L'idéal dans un programme C++ est de n'avoir aucun appel à delete ou delete[].
De plus, les smart-pointer font partie de la nouvelle norme C++ : C++1x.
Il est donc essentiel aujourd'hui de connaître les classes suivantes :


La clé primaire est de type long par défaut. Est-il possible d'utiliser une clé de type QString ou autre ?

Il est possible de définir un identifiant unique de type QString ou autre avec la librairie QxOrm.
Par défaut, l'identifiant unique est de type long.
Pour indiquer qu'une classe a un identifiant unique de type QString ou autre, il faut spécialiser le template qx::trait::get_primary_key.
Pour simplifier, vous pouvez utiliser la macro : QX_REGISTER_PRIMARY_KEY(myClass, QString).

Attention : la macro QX_REGISTER_PRIMARY_KEY doit être utilisée avant la macro QX_REGISTER_HPP_... dans la définition de votre classe, sinon une erreur de compilation se produit.


Comment activer/désactiver le module QxMemLeak pour la détection automatique des fuites mémoires ?

Le module QxMemLeak permet une détection rapide des fuites mémoire en mode Debug une fois l'exécution du programme terminée (avec indication du fichier et de la ligne => style MFC de Microsoft).
Ce module a été développé par Wu Yongwei et a subi quelques modifications pour être intégré dans QxOrm.
Si un autre outil est déjà utilisé dans vos projets (Valgrind par exemple), cette fonctionnalité ne doit pas être activée.
Pour activer/désactiver le module QxMemLeak, il suffit de modifier la constante _QX_USE_MEM_LEAK_DETECTION définie dans le fichier QxConfig.h.
Une recompilation de la librairie QxOrm est nécessaire pour prendre en compte cette modification.




QxOrm