QxOrm Windows Linux Macintosh C++

Home Download Quick sample Tutorial (4)
Manual (2)
Forum Our customers

QxOrm >> Tutorial >> qxBlog
Current version :  QxOrm 1.4.4 - QxOrm library online class documentation
QxEntityEditor 1.2.2
Version française du site Web site english version
Select a tutorial : Tuto n°1 : qxBlog Tuto n°2 : qxClientServer Tuto n°3 : install QxOrm Tuto n°4 : video QxEntityEditor


In this chapter, we will see several features of QxOrm library with the creation of a C++ project : qxBlog - blog management in C++.
qxBlog tutorial step by step :
qt_ambassador
QxOrm library has been accepted into the Qt Ambassador Program
Note : there is a similar project in './test/qxBlogCompositeKey/' directory to show how to define an id with multi-columns in database (composite key).
For more details about 'multi-columns primary key' : read the manual here.


1- qxBlog project - blog management in C++ :
  • blog : 1 blog is written by 1 author, can have many comment and can be put inside many category
  • author : 1 author can write many blog
  • comment : 1 comment belongs to 1 blog
  • category : 1 category contains many blog

2- all files in qxBlog project :

./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

Note : tutorial source code is available in ./test/qxBlog/ folder of your QxOrm package.
qxBlog.sqlite file is the tutorial database in the format SQLite.


3- qxBlog.pro file :

This file is necessary to compile and build the project with the command qmake provided by Qt library.
The tool qmake is multi-platform, so qxBlog project can be compiled under Windows, Linux, Mac OS X, etc...
The file qxBlog.pro contains the list of all files in the project (header + source) and all dependencies (QxOrm.pri file contains all dependencies with boost and Qt libraries).
qxBlog.pro contains an important constant (_BUILDING_QX_BLOG) to know if the project is compiling (cf. export.h and DLL mechanism under Windows to import or export functions, classes...).

qxBlog.pro


4- export.h file :

A DLL Windows needs this file to manage 'export/import' of classes, functions...
QxOrm uses the same mechanism to provide some functionalities : so the file export.h is necessary to all projects using QxOrm library.

Note : quick resume of DLL mechanism under Windows :

  • when a DLL is compiling, each class is exported
  • when another DLL is compiling, each class of the first DLL needs to be imported to be used

#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- precompiled.h file :

precompiled header file reduces compilation times of a C++ project.
QxOrm uses meta-programming concept to provide a lot of functionalities.
meta-programming is costly in compilation times, so your project will be compiled much more quickly with the file precompiled.h.

Last but not least, another advantage is that the file QxOrm.h includes the basic functionalities of libraries boost and Qt.
It is thus not necessary anymore to write #include <QtCore/QString.h> to use the class QString of Qt for example.
In the same way, there is no need anymore to write #include <boost/shared_ptr.hpp> to use smart pointers of boost library.

#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- author.h and author.cpp (relationship one-to-many) :

1 author can write many blog : we will see how to use relationship one-to-many.
In the database, there is 2 tables :

qxBlog.table.author

In the C++ source code, the properties of author class belong to columns of author table in the database.
So 1 instance of author class in the C++ source code belong to 1 row of author table in the database.
This mechanism provides C++ source code easy to develop and to maintain.

We add 1 method to our author class : int age() to retrieve the age with the data returned by the database.
We define also 2 typedef : a smart-pointer to an object author, and a list of author.
author class need an id of QString type (by default, QxOrm provides id of long type) : we use the macro QX_REGISTER_PRIMARY_KEY(author, QString) to specialize the template.

#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 };
// -- properties
   QString     m_id;
   QString     m_name;
   QDate       m_birthdate;
   enum_sex    m_sex;
   list_blog   m_blogX;
// -- contructor, virtual destructor
   author() : m_id(0), m_sex(unknown) { ; }
   virtual ~author() { ; }
// -- methods
   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- comment.h and comment.cpp (relationship many-to-one) :

1 comment belongs to 1 blog and 1 blog can contain many comment : we will see how to use relationship many-to-one.
In the database, there is 2 tables :

qxBlog.table.comment

Like author class, we define 2 typedef : a smart-pointer to a comment object and a list of comment.

#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;
// -- properties
   long        m_id;
   QString     m_text;
   QDateTime   m_dt_create;
   blog_ptr    m_blog;
// -- contructor, virtual destructor
   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- category.h and category.cpp (relationship many-to-many) :

1 category contains many blog and 1 blog can be put inside many category : we will see how to use relationship many-to-many.
This kind of relationship need a new table in the database to save the list of id for each relationship.
So in the database, there is 3 tables :

qxBlog.table.category

Like author class and comment class, we define 2 typedef : a smart-pointer to a category object and a list of category.

#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;
// -- properties
   long        m_id;
   QString     m_name;
   QString     m_desc;
   list_blog   m_blogX;
// -- contructor, virtual destructor
   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- blog.h and blog.cpp (relationship one-to-many, many-to-one and many-to-many) :

1 blog is written by 1 author, can have many comment and can be put inside many category.
So this class has 3 relationships : one-to-many, many-to-one and many-to-many.
Like other classes, we define 2 typedef : a smart-pointer to a blog object and a list of blog.

#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:
// -- properties
   long           m_id;
   QString        m_text;
   QDateTime      m_dt_creation;
   author_ptr     m_author;
   list_comment   m_commentX;
   list_category  m_categoryX;
// -- contructor, virtual destructor
   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- main.cpp file :

QxOrm can communicate with many databases (see the list of databases in Qt web site) => persistence.
QxOrm provides also 2 other important functionalities :
  • serialization : binary, XML and JSON format
  • reflection (or introspection) : access to classes definitions, retrieve properties and call classes methods

#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[])
{
   // Qt application
   QApplication app(argc, argv);

   // Parameters to connect to database
   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("");

   // Ensure there is no element in database
   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>();

   // Create a list of 3 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);

   // Insert list of 3 author into database
   daoError = qx::dao::insert(authorX);
   qAssert(qx::dao::count<author>() == 3);

   // Clone author n°2 : '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);

   // Create a query to fetch only female author : 'author_id_2' and '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);

   // Dump list of female author (XML or JSON serialization)
   qx::dump(list_of_female_author);

   // Create 3 categories
   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";

   { // Create a scope to destroy temporary connexion to database

   // Open a transaction to database
   QSqlDatabase db = qx::QxSqlDatabase::getDatabase();
   bool bCommit = db.transaction();

   // Insert 3 categories into database, use 'db' parameter for the transaction
   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);

   // Terminate transaction => commit or rollback if there is error
   if (bCommit) { db.commit(); }
   else { db.rollback(); }

   } // End of scope : 'db' is destroyed

   // Create a blog with the class name (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;

   // Insert 'blog_1' into database with 'save()' method
   daoError = qx::dao::save(blog_1);

   // Modify 'blog_1' properties and save into database
   blog_1->m_text = "update blog_text_1";
   blog_1->m_author = author_2;
   daoError = qx::dao::save(blog_1);

   // Add 2 comments to '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);

   // Add 2 categories to 'blog_1' => must insert into extra-table 'category_blog'
   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);

   // Fetch blog into a new variable with all relation : 'author', 'comment' and 'category'
   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");

   // Dump 'blog_tmp' result from database (XML or JSON serialization)
   qx::dump(blog_tmp);

   // Call 'age()' method with class name and method name (reflection)
   qx_bool bInvokeOk = qx::QxClassX::invoke("author", "age", author_1);
   qAssert(bInvokeOk);

   return 0;
}


Click here to see output debug trace after execution of qxBlog program...

[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>'


Important note : QxOrm doesn't want to hide sql query (by default, all sql queries are displayed).
QxOrm cannot resolve all problems with sql and databases, so it is sometimes necessary to use QtSql engine of Qt library to write your own sql query or stored procedure.


11- relationship one-to-one with person class :

QxOrm can also be used with relationship one-to-one.
We add to our project the class person (person.h and person.cpp files) : 1 person is 1 author.
So person and author share the same id in the database : this is a relationship one-to-one.
There is 2 tables in the database :

qxBlog.table.person

Note : we add to person table the column mother_id. So we can retrieve the mother (of type person) belongs to 1 person : this is a relationship many-to-one on the same table person. Moreover, if 1 person is a mother, we can retrieve the list of childs (of type person) : this is a relationship one-to-many on the same table person.



QxOrm © 2017 Lionel Marty - contact@qxorm.com