QxOrm Windows Linux Macintosh C++

Accueil T�l�chargement Exemple rapide Tutoriel (4)
Manuel (2)
Forum Nos clients

QxOrm >> Tutoriel >> qxBlog
Version courante :  QxOrm 1.5.0 - documentation en ligne de la biblioth�que QxOrm - GitHub
QxEntityEditor 1.2.8
Version fran�aise du site Web site english version
S�lection du tutoriel : Tuto n�1 : qxBlog Tuto n�2 : qxClientServer Tuto n�3 : install QxOrm Tuto n�4 : video QxEntityEditor


Dans ce chapitre, nous allons traiter plusieurs fonctionnalit�s de la biblioth�que QxOrm avec la cr�ation d'un projet de gestion d'un blog en C++.
Le tutoriel qxBlog est constitu� des �tapes suivantes :
qt_ambassador
QxOrm library has been accepted into the Qt Ambassador Program
Remarque : ce tutoriel est �galement disponible sur le site www.developpez.com.

Autre remarque : il existe un projet similaire dans le dossier './test/qxBlogCompositeKey/' pour montrer comment d�finir des identifiants sur plusieurs colonnes (composite key).
Pour plus d'informations sur cette notion de 'multi-columns primary key' : suivre ce lien du manuel utilisateur.


1- Projet qxBlog - gestion d'un blog en C++ avec les tables suivantes :
  • blog : un blog est �crit par un author, peut avoir plusieurs comment et peut �tre associ� � plusieurs category ;
  • author : un author peut r�diger plusieurs blog ;
  • comment : un comment est associ� � un blog ;
  • category : une category r�f�rence plusieurs blog.

2- Le projet qxBlog du tutoriel a l'arborescence suivante :

./qxBlog/
./qxBlog/qxBlog.pro
./qxBlog/qxBlog.sqlite
./qxBlog/include/precompiled.h
./qxBlog/include/export.h
./qxBlog/include/author.h
./qxBlog/include/blog.h
./qxBlog/include/category.h
./qxBlog/include/comment.h
./qxBlog/src/author.cpp
./qxBlog/src/blog.cpp
./qxBlog/src/category.cpp
./qxBlog/src/comment.cpp
./qxBlog/src/main.cpp

Remarque : le code source de ce tutoriel est disponible dans le dossier ./test/qxBlog/ de la distribution de QxOrm.
Le fichier qxBlog.sqlite correspond � la base de donn�es du tutoriel au format SQLite.


3- Contenu du fichier qxBlog.pro :

Ce fichier permet la compilation du projet par l'outil qmake fourni par le framework Qt.
L'outil qmake est multiplateforme, ce qui signifie que le projet qxBlog peut �tre compil� sous Windows, Linux, Mac, etc.
Le fichier qxBlog.pro d�crit la liste de tous les fichiers du projet (header + source) ainsi que les d�pendances du projet.
Le projet qxBlog est d�pendant de la biblioth�que QxOrm qui est elle-m�me d�pendante des excellents frameworks boost et Qt.
Pour simplifier la gestion des d�pendances du projet, il est possible d'inclure le fichier QxOrm.pri.
Une information importante � renseigner dans le fichier qxBlog.pro est la d�finition d'une variable indiquant que l'on est en train de compiler le projet (voir le fichier export.h). En effet, tout comme le m�canisme des DLL sous Windows, la biblioth�que QxOrm a besoin de cette information pour exporter ou importer certaines classes. Pour notre projet, cette variable se nomme _BUILDING_QX_BLOG.

qxBlog.pro


4- Contenu du fichier export.h :

L'�criture d'une DLL sous Windows impose d'avoir un fichier de ce type pour la gestion des 'export/import' des classes, fonctions, variables, etc.
QxOrm utilise ce m�me m�canisme pour fournir certaines fonctionnalit�s : le fichier export.h est donc indispensable pour tous les projets qui d�pendent de QxOrm.

Remarque : pour simplifier, il est possible de sch�matiser le m�canisme des DLL de la fa�on suivante :

  • lorsque la DLL est compil�e, l'outil de compilation exporte chaque classe ;
  • lorsqu'une autre DLL d�pendante de la pr�c�dente est compil�e, l'outil de compilation importe les classes n�cessaires de la DLL pr�c�dente.

#ifndef _QX_BLOG_EXPORT_H_
#define _QX_BLOG_EXPORT_H_

#ifdef _BUILDING_QX_BLOG
#define QX_BLOG_DLL_EXPORT QX_DLL_EXPORT_HELPER
#else // _BUILDING_QX_BLOG
#define QX_BLOG_DLL_EXPORT QX_DLL_IMPORT_HELPER
#endif // _BUILDING_QX_BLOG

#ifdef _BUILDING_QX_BLOG
#define QX_REGISTER_HPP_QX_BLOG QX_REGISTER_HPP_EXPORT_DLL
#define QX_REGISTER_CPP_QX_BLOG QX_REGISTER_CPP_EXPORT_DLL
#else // _BUILDING_QX_BLOG
#define QX_REGISTER_HPP_QX_BLOG QX_REGISTER_HPP_IMPORT_DLL
#define QX_REGISTER_CPP_QX_BLOG QX_REGISTER_CPP_IMPORT_DLL
#endif // _BUILDING_QX_BLOG

#endif // _QX_BLOG_EXPORT_H_


5- Contenu du fichier precompiled.h :

Il s'agit d'un en-t�te pr�compil� (precompiled header) permettant d'optimiser les temps de compilation du projet.
En effet, QxOrm utilise les techniques de m�taprogrammation pour fournir l'ensemble de ses fonctionnalit�s.
La m�taprogrammation �tant couteuse en temps de compilation, un projet C++ se compilera beaucoup plus vite avec un fichier precompiled.h.
Un seul fichier d'en-t�te est n�cessaire pour disposer de l'ensemble des fonctionnalit�s de QxOrm : le fichier QxOrm.h.

#ifndef _QX_BLOG_PRECOMPILED_HEADER_H_
#define _QX_BLOG_PRECOMPILED_HEADER_H_

#include <QxOrm.h>

#include "export.h"

#endif // _QX_BLOG_PRECOMPILED_HEADER_H_


6- Contenu des fichiers author.h et author.cpp (relation one-to-many) :

Un author est une personne qui peut r�diger plusieurs blog : nous allons ainsi montrer comment utiliser la relation de type one-to-many.
Au niveau base de donn�es, voici les deux tables qui correspondent :

qxBlog.table.author

Dans le code C++, les propri�t�s de la classe author sont le sym�trique des champs de la table author dans la base de donn�es.
Donc une instance de la classe author dans le code C++ correspond � une ligne de la table author dans la base de donn�es.
Ce principe permet d'�crire du code C++ simple de compr�hension et facile � maintenir.

Nous ajoutons une m�thode � notre classe author : int age() qui calculera l'�ge en fonction de la date de naissance envoy�e par la base de donn�es.
Nous �crivons �galement deux typedef pour repr�senter un pointeur (smart-pointer) vers un objet author ainsi qu'une collection de author.
La classe author a un identifiant de type QString (par d�faut, un identifiant dans le contexte QxOrm est de type long) : nous utilisons la macro QX_REGISTER_PRIMARY_KEY(author, QString) pour sp�cialiser le template.
La classe author s'�crit de la fa�on suivante :

#ifndef _QX_BLOG_AUTHOR_H_
#define _QX_BLOG_AUTHOR_H_

class blog;

class QX_BLOG_DLL_EXPORT author
{
public:
// -- typedef
   typedef boost::shared_ptr<blog> blog_ptr;
   typedef std::vector<blog_ptr> list_blog;
// -- enum
   enum enum_sex { male, female, unknown };
// -- propri�t�s
   QString     m_id;
   QString     m_name;
   QDate       m_birthdate;
   enum_sex    m_sex;
   list_blog   m_blogX;
// -- constructeur, destructeur virtuel
   author() : m_id(0), m_sex(unknown) { ; }
   virtual ~author() { ; }
// -- m�thodes
   int age() const;
};

QX_REGISTER_PRIMARY_KEY(author, QString)
QX_REGISTER_HPP_QX_BLOG(author, qx::trait::no_base_class_defined, 0)

typedef boost::shared_ptr<author> author_ptr;
typedef qx::QxCollection<QString, author_ptr> list_author;

#endif // _QX_BLOG_AUTHOR_H_

#include "../include/precompiled.h"

#include "../include/author.h"
#include "../include/blog.h"

#include <QxOrm_Impl.h>

QX_REGISTER_CPP_QX_BLOG(author)

namespace qx {
template <> void register_class(QxClass<author> & t)
{
   t.id(& author::m_id, "author_id");

   t.data(& author::m_name, "name");
   t.data(& author::m_birthdate, "birthdate");
   t.data(& author::m_sex, "sex");

   t.relationOneToMany(& author::m_blogX, "list_blog", "author_id");

   t.fct_0<int>(& author::age, "age");
}}

int author::age() const
{
   if (! m_birthdate.isValid()) { return -1; }
   return (QDate::currentDate().year() - m_birthdate.year());
}


7- Contenu des fichiers comment.h et comment.cpp (relation many-to-one) :

Un comment est associ� � un blog et un blog peut contenir plusieurs comment : nous allons ainsi montrer comment utiliser la relation de type many-to-one.
Au niveau base de donn�es, voici les deux tables qui correspondent (nous reprenons la table blog vue pr�c�demment) :

qxBlog.table.comment

De m�me que pour la classe author, nous �crivons deux typedef pour repr�senter un pointeur vers un objet comment ainsi qu'une collection de comment.
La classe comment s'�crit de la fa�on suivante :

#ifndef _QX_BLOG_COMMENT_H_
#define _QX_BLOG_COMMENT_H_

class blog;

class QX_BLOG_DLL_EXPORT comment
{
public:
// -- typedef
   typedef boost::shared_ptr<blog> blog_ptr;
// -- propri�t�s
   long        m_id;
   QString     m_text;
   QDateTime   m_dt_create;
   blog_ptr    m_blog;
// -- constructeur, destructeur virtuel
   comment() : m_id(0) { ; }
   virtual ~comment() { ; }
};

QX_REGISTER_HPP_QX_BLOG(comment, qx::trait::no_base_class_defined, 0)

typedef boost::shared_ptr<comment> comment_ptr;
typedef QList<comment_ptr> list_comment;

#endif // _QX_BLOG_COMMENT_H_

#include "../include/precompiled.h"

#include "../include/comment.h"
#include "../include/blog.h"

#include <QxOrm_Impl.h>

QX_REGISTER_CPP_QX_BLOG(comment)

namespace qx {
template <> void register_class(QxClass<comment> & t)
{
   t.id(& comment::m_id, "comment_id");

   t.data(& comment::m_text, "comment_text");
   t.data(& comment::m_dt_create, "date_creation");

   t.relationManyToOne(& comment::m_blog, "blog_id");
}}


8- Contenu des fichiers category.h et category.cpp (relation many-to-many) :

Une category r�f�rence plusieurs blog et un blog peut appartenir � plusieurs category : nous allons ainsi montrer comment utiliser la relation de type many-to-many.
Ce type de relation implique une table suppl�mentaire dans la base de donn�es pour stocker la liste des id de chaque c�t� des relations.
Au niveau base de donn�es, voici les trois tables qui correspondent (nous reprenons la table blog vue pr�c�demment) :

qxBlog.table.category

De m�me que pour les classes author et comment, nous �crivons deux typedef pour repr�senter un pointeur vers un objet category ainsi qu'une collection de category.
La classe category s'�crit de la fa�on suivante :

#ifndef _QX_BLOG_CATEGORY_H_
#define _QX_BLOG_CATEGORY_H_

class blog;

class QX_BLOG_DLL_EXPORT category
{
public:
// -- typedef
   typedef boost::shared_ptr<blog> blog_ptr;
   typedef qx::QxCollection<long, blog_ptr> list_blog;
// -- propri�t�s
   long        m_id;
   QString     m_name;
   QString     m_desc;
   list_blog   m_blogX;
// -- constructeur, destructeur virtuel
   category() : m_id(0) { ; }
   virtual ~category() { ; }
};

QX_REGISTER_HPP_QX_BLOG(category, qx::trait::no_base_class_defined, 0)

typedef QSharedPointer<category> category_ptr;
typedef qx::QxCollection<long, category_ptr> list_category;

#endif // _QX_BLOG_CATEGORY_H_

#include "../include/precompiled.h"

#include "../include/category.h"
#include "../include/blog.h"

#include <QxOrm_Impl.h>

QX_REGISTER_CPP_QX_BLOG(category)

namespace qx {
template <> void register_class(QxClass<category> & t)
{
   t.id(& category::m_id, "category_id");

   t.data(& category::m_name, "name");
   t.data(& category::m_desc, "description");

   t.relationManyToMany(& category::m_blogX, "list_blog", "category_blog", "category_id", "blog_id");
}}


9- Contenu des fichiers blog.h et blog.cpp (relations one-to-many, many-to-one et many-to-many) :

Un blog est �crit par un author, peut avoir plusieurs comment et peut �tre associ� � plusieurs category. Cette classe contient donc trois relations : one-to-many, many-to-one et many-to-many.

Remarque : QxOrm g�re �galement le type de relation one-to-one qui est cependant beaucoup moins utilis�e que les autres relations.
Un exemple de type de relation one-to-one est disponible en annexe de ce tutoriel avec la classe/table person : une person correspond � un author.

De m�me que pour les autres classes, nous �crivons deux typedef pour repr�senter un pointeur vers un objet blog ainsi qu'une collection de blog.
La classe blog s'�crit de la fa�on suivante :

#ifndef _QX_BLOG_BLOG_H_
#define _QX_BLOG_BLOG_H_

#include "author.h"
#include "comment.h"
#include "category.h"

class QX_BLOG_DLL_EXPORT blog
{
public:
// -- propri�t�s
   long           m_id;
   QString        m_text;
   QDateTime      m_dt_creation;
   author_ptr     m_author;
   list_comment   m_commentX;
   list_category  m_categoryX;
// -- constructeur, destructeur virtuel
   blog() : m_id(0) { ; }
   virtual ~blog() { ; }
};

QX_REGISTER_HPP_QX_BLOG(blog, qx::trait::no_base_class_defined, 0)

typedef boost::shared_ptr<blog> blog_ptr;
typedef std::vector<blog_ptr> list_blog;

#endif // _QX_BLOG_BLOG_H_

#include "../include/precompiled.h"

#include "../include/blog.h"

#include <QxOrm_Impl.h>

QX_REGISTER_CPP_QX_BLOG(blog)

namespace qx {
template <> void register_class(QxClass<blog> & t)
{
   t.id(& blog::m_id, "blog_id");

   t.data(& blog::m_text, "blog_text");
   t.data(& blog::m_dt_creation, "date_creation");

   t.relationManyToOne(& blog::m_author, "author_id");
   t.relationOneToMany(& blog::m_commentX, "list_comment", "blog_id");
   t.relationManyToMany(& blog::m_categoryX, "list_category", "category_blog", "blog_id", "category_id");
}}


10- Contenu du fichier main.cpp :

QxOrm permet de communiquer de mani�re simple et performante avec de nombreuses bases de donn�es (voir la liste des bases de donn�es support�es sur le site de Qt).
Il est recommand� d'utiliser un pilote sp�cifique � la base de donn�es afin d'optimiser les performances : le pilote QODBC, bien que g�n�rique et permettant de s'interfacer avec la plupart des bases de donn�es du march�, sera moins performant qu'un pilote natif (par exemple, le pilote QMYSQL pour une base de donn�es MySQL).

Outre la persistance, QxOrm poss�de �galement d'autres fonctionnalit�s int�ressantes li�es � la gestion des donn�es :
  • la s�rialisation automatique des donn�es ou collections de donn�es au format binaire, XML et JSON ;
  • la r�flexion (ou introspection) permettant d'acc�der � la d�finition des classes param�tr�es dans le contexte QxOrm ainsi que l'appel automatique des m�thodes de classes.

#include "../include/precompiled.h"

#include <QtGui/qapplication.h>

#include "../include/blog.h"
#include "../include/author.h"
#include "../include/comment.h"
#include "../include/category.h"

#include <QxOrm_Impl.h>

int main(int argc, char * argv[])
{
   // Initialisation de l'objet application du framework Qt
   QApplication app(argc, argv);

   // Param�tres de connexion � la base de donn�es
   qx::QxSqlDatabase::getSingleton()->setDriverName("QSQLITE");
   qx::QxSqlDatabase::getSingleton()->setDatabaseName("./qxBlog.sqlite");
   qx::QxSqlDatabase::getSingleton()->setHostName("localhost");
   qx::QxSqlDatabase::getSingleton()->setUserName("root");
   qx::QxSqlDatabase::getSingleton()->setPassword("");

   // Vide toutes les tables de la base de donn�es
   QSqlError daoError = qx::dao::delete_all<author>();
   daoError = qx::dao::delete_all<comment>();
   daoError = qx::dao::delete_all<category>();
   daoError = qx::dao::delete_all<blog>();

   // Cr�ation d'une liste de trois 'author'
   author_ptr author_1; author_1.reset(new author());
   author_ptr author_2; author_2.reset(new author());
   author_ptr author_3; author_3.reset(new author());

   author_1->m_id = "author_id_1"; author_1->m_name = "author_1";
   author_1->m_sex = author::male; author_1->m_birthdate = QDate::currentDate();
   author_2->m_id = "author_id_2"; author_2->m_name = "author_2";
   author_2->m_sex = author::female; author_2->m_birthdate = QDate::currentDate();
   author_3->m_id = "author_id_3"; author_3->m_name = "author_3";
   author_3->m_sex = author::female; author_3->m_birthdate = QDate::currentDate();

   list_author authorX;
   authorX.insert(author_1->m_id, author_1);
   authorX.insert(author_2->m_id, author_2);
   authorX.insert(author_3->m_id, author_3);

   // Insertion de la liste des trois 'author' dans la base de donn�es
   daoError = qx::dao::insert(authorX);
   qAssert(qx::dao::count<author>() == 3);

   // Cr�ation d'un clone de l'instance 'author_id_2'
   author_ptr author_clone = qx::clone(* author_2);
   qAssert(author_clone->m_id == "author_id_2");
   qAssert(author_clone->m_sex == author::female);

   // Construit une requ�te pour r�cup�rer uniquement les 'author' de type 'female', soit 'author_id_2' et 'author_id_3'
   qx::QxSqlQuery query("WHERE author.sex = :sex");
   query.bind(":sex", author::female);

   list_author list_of_female_author;
   daoError = qx::dao::fetch_by_query(query, list_of_female_author);
   qAssert(list_of_female_author.count() == 2);

   // Affiche la liste des 'author' de type 'female' dans un flux XML (ou JSON)
   qx::dump(list_of_female_author);

   // Cr�ation de trois 'category' pour classer les 'blog'
   category_ptr category_1 = category_ptr(new category());
   category_ptr category_2 = category_ptr(new category());
   category_ptr category_3 = category_ptr(new category());

   category_1->m_name = "category_1"; category_1->m_desc = "desc_1";
   category_2->m_name = "category_2"; category_2->m_desc = "desc_2";
   category_3->m_name = "category_3"; category_3->m_desc = "desc_3";

   { // Ouverture d'un 'scope' pour g�rer la destruction d'une connexion temporaire � la base de donn�es

   // Cr�ation d'une connexion temporaire � la base de donn�es et ouverture d'une transaction
   QSqlDatabase db = qx::QxSqlDatabase::getDatabase();
   bool bCommit = db.transaction();

   // Insertion de trois 'category' dans la base de donn�es en utilisant la connexion temporaire 'db'
   daoError = qx::dao::insert(category_1, (& db));    bCommit = (bCommit && ! daoError.isValid());
   daoError = qx::dao::insert(category_2, (& db));    bCommit = (bCommit && ! daoError.isValid());
   daoError = qx::dao::insert(category_3, (& db));    bCommit = (bCommit && ! daoError.isValid());

   qAssert(bCommit);
   qAssert(category_1->m_id != 0);
   qAssert(category_2->m_id != 0);
   qAssert(category_3->m_id != 0);

   // Fin de la transaction => 'commit' ou 'rollback' en cas d'erreur
   if (bCommit) { db.commit(); }
   else { db.rollback(); }

   } // Fermeture du 'scope' : l'instance 'db' est d�truite

   // Cr�ation d'un 'blog' � partir du nom de la classe (design pattern 'factory')
   boost::any blog_any = qx::create("blog");
   blog_ptr blog_1 = boost::any_cast<blog_ptr>(blog_any);
   blog_1->m_text = "blog_text_1";
   blog_1->m_dt_creation = QDateTime::currentDateTime();
   blog_1->m_author = author_1;

   // Insertion de 'blog_1' dans la base de donn�es avec la m�thode 'save()'
   daoError = qx::dao::save(blog_1);

   // Modification des propri�t�s de 'blog_1' et mise � jour dans la base de donn�es
   blog_1->m_text = "update blog_text_1";
   blog_1->m_author = author_2;
   daoError = qx::dao::save(blog_1);

   // Ajoute deux commentaires � 'blog_1'
   comment_ptr comment_1; comment_1.reset(new comment());
   comment_ptr comment_2; comment_2.reset(new comment());

   comment_1->m_text = "comment_1 text";
   comment_1->m_dt_create = QDateTime::currentDateTime();
   comment_1->m_blog = blog_1;
   comment_2->m_text = "comment_2 text";
   comment_2->m_dt_create = QDateTime::currentDateTime();
   comment_2->m_blog = blog_1;

   daoError = qx::dao::insert(comment_1);
   daoError = qx::dao::insert(comment_2);
   qAssert(qx::dao::count<comment>() == 2);

   // Associe deux 'category' � 'blog_1' => n�cessite une 3�me table pour la relation 'many-to-many'
   blog_1->m_categoryX.insert(category_1->m_id, category_1);
   blog_1->m_categoryX.insert(category_3->m_id, category_3);
   daoError = qx::dao::save_with_relation("list_category", blog_1);

   // R�cup�re avec une seule m�thode 'blog_1' et toutes ses relations dans la base de donn�es
   blog_ptr blog_tmp; blog_tmp.reset(new blog());
   blog_tmp->m_id = blog_1->m_id;
   daoError = qx::dao::fetch_by_id_with_all_relation(blog_tmp);

   qAssert(blog_tmp->m_commentX.count() == 2);
   qAssert(blog_tmp->m_categoryX.count() == 2);
   qAssert(blog_tmp->m_text == "update blog_text_1");
   qAssert(blog_tmp->m_author && blog_tmp->m_author->m_id == "author_id_2");

   // Affiche 'blog_tmp' provenant de la base de donn�es dans un flux XML (ou JSON)
   qx::dump(blog_tmp);

   // Invoque la m�thode 'age()' de la classe 'author' par le m�canisme de r�flexion (ou introspection)
   qx_bool bInvokeOk = qx::QxClassX::invoke("author", "age", author_1);
   qAssert(bInvokeOk);

   return 0;
}


Voici les traces g�n�r�es apr�s ex�cution du programme qxBlog :

[QxOrm] qx::QxSqlDatabase : create new database connection in thread '4456' with key '{e986c95d-1cb0-4368-ad9c-3dd4ccd20b84}'
[QxOrm] sql query (93 ms) : DELETE FROM author
[QxOrm] sql query (63 ms) : DELETE FROM comment
[QxOrm] sql query (94 ms) : DELETE FROM category
[QxOrm] sql query (78 ms) : DELETE FROM blog
[QxOrm] sql query (62 ms) : INSERT INTO author (author_id, name, birthdate, sex) VALUES (:author_id, :name, :birthdate, :sex)
[QxOrm] sql query (0 ms) : SELECT COUNT(*) FROM author
[QxOrm] sql query (0 ms) : SELECT author.author_id AS author_author_id_0, author.name AS author_name_0, author.birthdate AS author_birthdate_0, author.sex AS author_sex_0 FROM author WHERE author.sex = :sex
[QxOrm] start dump 'qx::QxCollection<QString, boost::shared_ptr<author>>'
<qx.QxCollection-QString_boost.shared_ptr-author-- class_id="0" tracking_level="0" version="0">
	<count>2</count>
	<item class_id="1" tracking_level="0" version="0">
		<first class_id="2" tracking_level="0" version="0">author_id_2</first>
		<second class_id="3" tracking_level="0" version="1">
			<px class_id="4" tracking_level="1" version="0" object_id="_0">
				<author_id>author_id_2</author_id>
				<name>author_2</name>
				<birthdate class_id="5" tracking_level="0" version="0">20100409</birthdate>
				<sex>1</sex>
				<list_blog class_id="6" tracking_level="0" version="0">
					<count>0</count>
					<item_version>1</item_version>
				</list_blog>
			</px>
		</second>
	</item>
	<item>
		<first>author_id_3</first>
		<second>
			<px class_id_reference="4" object_id="_1">
				<author_id>author_id_3</author_id>
				<name>author_3</name>
				<birthdate>20100409</birthdate>
				<sex>1</sex>
				<list_blog>
					<count>0</count>
					<item_version>1</item_version>
				</list_blog>
			</px>
		</second>
	</item>
</qx.QxCollection-QString_boost.shared_ptr-author-->
[QxOrm] end dump 'qx::QxCollection<QString, boost::shared_ptr<author>>'
[QxOrm] sql query (0 ms) : INSERT INTO category (name, description) VALUES (:name, :description)
[QxOrm] sql query (0 ms) : INSERT INTO category (name, description) VALUES (:name, :description)
[QxOrm] sql query (0 ms) : INSERT INTO category (name, description) VALUES (:name, :description)
[QxOrm] sql query (0 ms) : INSERT INTO blog (blog_text, date_creation, author_id) VALUES (:blog_text, :date_creation, :author_id)
[QxOrm] sql query (0 ms) : SELECT blog.blog_id AS blog_blog_id_0 FROM blog WHERE blog_blog_id_0 = :blog_id
[QxOrm] sql query (0 ms) : UPDATE blog SET blog_id = :blog_id, blog_text = :blog_text, date_creation = :date_creation, author_id = :author_id WHERE blog_id = :blog_id_bis
[QxOrm] sql query (78 ms) : INSERT INTO comment (comment_text, date_creation, blog_id) VALUES (:comment_text, :date_creation, :blog_id)
[QxOrm] sql query (78 ms) : INSERT INTO comment (comment_text, date_creation, blog_id) VALUES (:comment_text, :date_creation, :blog_id)
[QxOrm] sql query (0 ms) : SELECT COUNT(*) FROM comment
[QxOrm] sql query (0 ms) : SELECT blog.blog_id AS blog_blog_id_0 FROM blog WHERE blog_blog_id_0 = :blog_id
[QxOrm] sql query (0 ms) : UPDATE blog SET blog_id = :blog_id, blog_text = :blog_text, date_creation = :date_creation, author_id = :author_id WHERE blog_id = :blog_id_bis
[QxOrm] sql query (0 ms) : SELECT category.category_id AS category_category_id_0 FROM category WHERE category_category_id_0 = :category_id
[QxOrm] sql query (0 ms) : UPDATE category SET category_id = :category_id, name = :name, description = :description WHERE category_id = :category_id_bis
[QxOrm] sql query (0 ms) : SELECT category.category_id AS category_category_id_0 FROM category WHERE category_category_id_0 = :category_id
[QxOrm] sql query (0 ms) : UPDATE category SET category_id = :category_id, name = :name, description = :description WHERE category_id = :category_id_bis
[QxOrm] sql query (extra-table) : DELETE FROM category_blog WHERE category_blog.blog_id = :blog_id
[QxOrm] sql query (extra-table) : INSERT INTO category_blog (blog_id, category_id) VALUES (:blog_id, :category_id)
[QxOrm] sql query (0 ms) : SELECT blog.blog_id AS blog_blog_id_0, blog.blog_text AS blog_blog_text_0, blog.date_creation AS blog_date_creation_0, blog.author_id AS blog_author_id_0, author_1.author_id AS author_1_author_id_0, author_1.name AS author_1_name_0, author_1.birthdate AS author_1_birthdate_0, author_1.sex AS author_1_sex_0, comment_2.comment_id AS comment_2_comment_id_0, comment_2.blog_id AS comment_2_blog_id_0, comment_2.comment_text AS comment_2_comment_text_0, comment_2.date_creation AS comment_2_date_creation_0, category_3.category_id AS category_3_category_id_0, category_3.name AS category_3_name_0, category_3.description AS category_3_description_0 FROM blog LEFT OUTER JOIN author author_1 ON author_1_author_id_0 = blog_author_id_0 LEFT OUTER JOIN comment comment_2 ON comment_2_blog_id_0 = blog_blog_id_0 LEFT OUTER JOIN category_blog ON blog_blog_id_0 = category_blog.blog_id LEFT OUTER JOIN category category_3 ON category_blog.category_id = category_3_category_id_0 WHERE blog_blog_id_0 = :blog_id
[QxOrm] start dump 'boost::shared_ptr<blog>'
<boost.shared_ptr-blog- class_id="0" tracking_level="0" version="1">
	<px class_id="1" tracking_level="1" version="0" object_id="_0">
		<blog_id>113</blog_id>
		<blog_text class_id="2" tracking_level="0" version="0">update blog_text_1</blog_text>
		<date_creation class_id="3" tracking_level="0" version="0">20100409162612000</date_creation>
		<author_id class_id="4" tracking_level="0" version="1">
			<px class_id="5" tracking_level="1" version="0" object_id="_1">
				<author_id>author_id_2</author_id>
				<name>author_2</name>
				<birthdate class_id="6" tracking_level="0" version="0">20100409</birthdate>
				<sex>1</sex>
				<list_blog class_id="7" tracking_level="0" version="0">
					<count>0</count>
					<item_version>1</item_version>
				</list_blog>
			</px>
		</author_id>
		<list_comment class_id="8" tracking_level="0" version="0">
			<count>2</count>
			<item class_id="9" tracking_level="0" version="1">
				<px class_id="10" tracking_level="1" version="0" object_id="_2">
					<comment_id>209</comment_id>
					<comment_text>comment_1 text</comment_text>
					<date_creation>20100409162612000</date_creation>
					<blog_id>
						<px class_id_reference="1" object_id="_3">
							<blog_id>113</blog_id>
							<blog_text></blog_text>
							<date_creation></date_creation>
							<author_id>
								<px class_id="-1"></px>
							</author_id>
							<list_comment>
								<count>0</count>
							</list_comment>
							<list_category class_id="11" tracking_level="0" version="0">
								<count>0</count>
							</list_category>
						</px>
					</blog_id>
				</px>
			</item>
			<item>
				<px class_id_reference="10" object_id="_4">
					<comment_id>210</comment_id>
					<comment_text>comment_2 text</comment_text>
					<date_creation>20100409162612000</date_creation>
					<blog_id>
						<px class_id_reference="1" object_id="_5">
							<blog_id>113</blog_id>
							<blog_text></blog_text>
							<date_creation></date_creation>
							<author_id>
								<px class_id="-1"></px>
							</author_id>
							<list_comment>
								<count>0</count>
							</list_comment>
							<list_category>
								<count>0</count>
							</list_category>
						</px>
					</blog_id>
				</px>
			</item>
		</list_comment>
		<list_category>
			<count>2</count>
			<item class_id="12" tracking_level="0" version="0">
				<first>355</first>
				<second class_id="13" tracking_level="0" version="0">
					<qt_shared_ptr class_id="14" tracking_level="1" version="0" object_id="_6">
						<category_id>355</category_id>
						<name>category_1</name>
						<description>desc_1</description>
						<list_blog class_id="15" tracking_level="0" version="0">
							<count>0</count>
						</list_blog>
					</qt_shared_ptr>
				</second>
			</item>
			<item>
				<first>357</first>
				<second>
					<qt_shared_ptr class_id_reference="14" object_id="_7">
						<category_id>357</category_id>
						<name>category_3</name>
						<description>desc_3</description>
						<list_blog>
							<count>0</count>
						</list_blog>
					</qt_shared_ptr>
				</second>
			</item>
		</list_category>
	</px>
</boost.shared_ptr-blog->
[QxOrm] end dump 'boost::shared_ptr<blog>'


Remarque importante : QxOrm n'a pas pour objectif de 'cacher' le code SQL (par d�faut toutes les requ�tes sont trac�es). M�me si QxOrm simplifie �norm�ment le code C++ et optimise ainsi les temps de d�veloppement et de maintenance d'un produit, il est tr�s important d'avoir de bonnes connaissances SQL.
QxOrm ne r�soudra pas toutes les probl�matiques li�es aux bases de donn�es (par exemple, jointure limit�e � deux tables dans une m�me requ�te), il sera alors n�cessaire d'utiliser directement le module QtSql de Qt en �crivant soi-m�me les requ�tes SQL ou les proc�dures stock�es.
Enfin, il faut �tre extr�mement vigilant au nombre de requ�tes effectu�es entre le programme C++ et la base de donn�es : un trop grand nombre d'appels � la base de donn�es peut d�t�riorer les performances d'une application. Il est important de ma�triser la notion de relations entre les classes ou bien de jointures pour les tables d'une base de donn�es (voir le syndrome n+1 SELECT que l'on peut rencontrer avec Hibernate ou tout autre ORM).

Pour plus d'informations sur le langage SQL, regardez l'excellent site de Fr�d�ric Brouart.

Autre remarque : il est important de signaler que les m�thodes void register_class(...) sont appel�es automatiquement et lorsque c'est n�cessaire par la biblioth�que QxOrm.
Par rapport � d'autres biblioth�ques qui n�cessitent un appel pour enregistrer les types de chaque classe, QxOrm permet un enregistrement automatique des classes, ce qui simplifie encore un peu plus le d�veloppement d'applications.


11- Annexe - exemple de relation one-to-one avec la classe person :

Ajoutons � notre projet la classe person (fichiers person.h et person.cpp) : une person correspond � un author dans la base de donn�es.
Ils partagent donc le m�me identifiant, c'est ce qu'on appelle une relation de type one-to-one.
Voici les deux tables de notre base de donn�es (nous reprenons la table author vue pr�c�demment) :

qxBlog.table.person

Remarque : nous ajoutons � la table person le champ mother_id. Nous pouvons ainsi conna�tre la m�re (de type person) associ�e � une person, ce qui correspond � une relation many-to-one sur la m�me table person. De plus, si une person est une m�re, nous pouvons conna�tre la liste de ses enfants (de type person), ce qui correspond � une relation one-to-many sur la m�me table person.


12- Remerciements

Je remercie tout particuli�rement Thibaut Cuvelier pour ses conseils pour l'am�lioration de ce tutoriel.
Je remercie �galement Claude Leloup pour ses relectures et corrections orthographiques.



QxOrm � 2011-202XDL Teamty - ic-east.com