Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

QxOrm - C++ ORM (Object Relational Mapping) Library

4.90/5 (61 votes)
24 Apr 2019GPL326 min read 143.7K   321  
QxOrm C++ library: Persistence (based on QtSql Qt library) - Serialization (based on boost::serialization library) - Reflection (introspection)
QxOrm
Qt Ambassador QxOrm library has been accepted into the Qt Ambassador Program:
QxOrm library web page on Qt official web site

Introduction

QxOrm is a C++ library designed to provide Object Relational Mapping (ORM) feature to C++ users.
With a simple C++ setting function by class (like Hibernate XML mapping file), you will have access to the following features:

  • Persistence: Communication with a lot of databases (with 1-1, 1-n, n-1 and n-n relationships)
  • Serialization: Binary and XML format
  • Reflection: Access to classes definitions, retrieve properties and call classes methods

QxOrm aims to simplify C++ development and provides a lot of functionalities. Here is a list of advantages of QxOrm:

  • Non intrusive: The C++ setting function doesn't modify class definition, QxOrm can be used in existing projects
  • No code generation
  • No XML mapping file
  • Classes don't need to inherit from a 'super object'
  • Template meta-programming: No macro hack
  • Works with Visual C++ 2008 or 2010 on Windows, GCC 4.4.1 on Linux and MinGW on Windows (other platforms will be tested soon: Mac, phones...)
  • Only one file <QxOrm.h> to include in precompiled-header (need precompiled-header file to reduce compilation times)

Before you install and compile QxOrm, you need the following libraries: boost (from version 1.38) and Qt (from version 4.5.0).

Note : you can generate automatically the Qt/C++ project source code using QxEntityEditor, the graphic editor for QxOrm library (more details on QxOrm website) !

Image 3

Using the Code

QxOrm library uses the following syntax for C++ source code:

  • All classes, functions, properties, etc. are defined under namespace qx
  • All macros of QxOrm library start with QX_...
  • All abstract classes (or interfaces) start with Ix (for example IxFactory is an interface to create an instance of object)
  • Other classes start with Qx (for example QxDataMember)
  • Containers of objects end with X (for example QxDataMemberX is a list of QxDataMember)
  • Functions to interact with databases are under namespace qx::dao (for example qx::dao::fetch_by_id())
  • Functions to serialize are under namespace qx::serialization (for example qx::serialization::xml::to_file())
  • The reflection engine can be used with qx::QxClassX (for example qx::QxClassX::invoke() to call a class method)
  • All traits classes are under namespace qx::trait (for example qx::trait::is_smart_ptr<T>)

Quick Sample

Quick sample step by step:

  1. drug.h file: Drug class definition with 3 properties : id, name and description
  2. drug.cpp file: 'setting function' implementation : void qx::register_class()
  3. main.cpp file: Basic functionalities of QxOrm library with drug class
  4. Execute program and trace output debug
  5. ./export_drugs.xml file created by the program

* ------------------------------------------------------------------------------------------
* 1- drug.h file : drug class definition with 3 properties : id, name and description
* ------------------------------------------------------------------------------------------

C++
#ifndef _CLASS_DRUG_H_
#define _CLASS_DRUG_H_

class drug
{
public:
   long id;
   QString name;
   QString description;

   drug() : id(0) { ; }
   virtual ~drug() { ; }
};

QX_REGISTER_HPP_MY_TEST_EXE(drug, qx::trait::no_base_class_defined, 1)

/* This macro is necessary to register 'drug' class in QxOrm context */
/* param 1 : the current class to register => 'drug' */
/* param 2 : the base class, if no base class, use the qx trait => 
/* 'qx::trait::no_base_class_defined' */
/* param 3 : the class version used by serialization to provide 'ascendant compatibility' */

#endif // _CLASS_DRUG_H_

* ------------------------------------------------------------------------------------------
* 2- drug.cpp file : 'setting function' implementation : void qx::register_class()
* ------------------------------------------------------------------------------------------

C++
#include "precompiled.h"   // Precompiled-header with '#include <QxOrm.h>' 
                           // and '#include "export.h"'
#include "drug.h"          // Class definition 'drug'
#include <QxMemLeak.h>     // Automatic memory leak detection

QX_REGISTER_CPP_MY_TEST_EXE(drug)   // This macro is necessary to register 
                                    // 'drug' class in QxOrm context

namespace qx {
template <> void register_class(QxClass<drug> & t)
{
  t.id(& drug::id, "id");               // Register 'drug::id' <=> primary key 
                                        // in your database
  t.data(& drug::name, "name", 1);      // Register 'drug::name' property with 
                                        // key 'name' and version '1'
  t.data(& drug::description, "desc");  // Register 'drug::description' property 
                                        // with key 'desc'
}}

* ------------------------------------------------------------------------------------------
* 3- main.cpp file : basic functionalities of QxOrm library with drug class
* ------------------------------------------------------------------------------------------

C++
#include "precompiled.h"
#include "drug.h"
#include <QxMemLeak.h>

int main(int argc, char * argv[])
{
   QApplication app(argc, argv); // Qt application

   // Create 3 new drugs
   // It is possible to use 'boost' and 'Qt' smart pointer : 
   // 'boost::shared_ptr', 'QSharedPointer', etc...
   typedef boost::shared_ptr<drug> drug_ptr;
   drug_ptr d1; d1.reset(new drug()); d1->name = "name1"; d1->description = "desc1";
   drug_ptr d2; d2.reset(new drug()); d2->name = "name2"; d2->description = "desc2";
   drug_ptr d3; d3.reset(new drug()); d3->name = "name3"; d3->description = "desc3";

   // Insert drugs into container
   // It is possible to use a lot of containers from 
   // 'std', 'boost', 'Qt' and 'qx::QxCollection<Key, Value>'
   typedef std::vector<drug_ptr> type_lst_drug;
   type_lst_drug lst_drug;
   lst_drug.push_back(d1);
   lst_drug.push_back(d2);
   lst_drug.push_back(d3);

   // Init parameters to communicate with a database
   qx::QxSqlDatabase::getSingleton()->setDriverName("QSQLITE");
   qx::QxSqlDatabase::getSingleton()->setDatabaseName("./test_qxorm.db");
   qx::QxSqlDatabase::getSingleton()->setHostName("localhost");
   qx::QxSqlDatabase::getSingleton()->setUserName("root");
   qx::QxSqlDatabase::getSingleton()->setPassword("");

   // Create table 'drug' into database to store drugs
   QSqlError daoError = qx::dao::create_table<drug>();

   // Insert drugs from container to database
   // 'id' property of 'd1', 'd2' and 'd3' are auto-updated
   daoError = qx::dao::insert(lst_drug);

   // Modify and update the second drug into database
   d2->name = "name2 modified";
   d2->description = "desc2 modified";
   daoError = qx::dao::update(d2);

   // Delete the first drug from database
   daoError = qx::dao::delete_by_id(d1);

   // Count drugs into database
   long lDrugCount = qx::dao::count<drug>();

   // Fetch drug with id '3' into a new variable
   drug_ptr d_tmp; d_tmp.reset(new drug());
   d_tmp->id = 3;
   daoError = qx::dao::fetch_by_id(d_tmp);

   // Export drugs from container to a file under xml format (serialization)
   qx::serialization::xml::to_file(lst_drug, "./export_drugs.xml");

   // Import drugs from xml file into a new container
   type_lst_drug lst_drug_tmp;
   qx::serialization::xml::from_file(lst_drug_tmp, "./export_drugs.xml");

   // Clone a drug
   drug_ptr d_clone = qx::clone(* d1);

   // Create a new drug by class name (factory)
   boost::any d_any = qx::create("drug");

   // Insert drugs container into 'qx::cache'
   qx::cache::set("drugs", lst_drug);

   // Remove all elements from 'qx::cache'
   qx::cache::clear();

   // Create a dummy memory leak
   drug * pDummy = new drug();

   return 0;
}

*-------------------------------------------------------------------------
* 4- execute program and trace output debug
* -------------------------------------------------------------------------

[QxOrm] qx::QxSqlDatabase : create new database connection in thread '3616' 
    with key '{d315250c-b5c9-46e0-9402-f800368a6673}'
[QxOrm] sql query (78 ms) : CREATE TABLE drug 
    (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name TEXT, desc TEXT)
[QxOrm] sql query (63 ms) : INSERT INTO drug (name, desc) VALUES (:name, :desc)
[QxOrm] sql query (62 ms) : UPDATE drug SET id = :id, 
    name = :name, desc = :desc WHERE id = :id_bis
[QxOrm] sql query (63 ms) : DELETE FROM drug WHERE id = :id
[QxOrm] sql query (0 ms) : SELECT COUNT(*) FROM drug
[QxOrm] sql query (0 ms) : SELECT drug.id AS drug_id_0, 
    drug.name AS drug_name_0, drug.desc AS 
    drug_desc_0 FROM drug WHERE drug_id_0 = :id
[QxOrm] Leaked object at 0xf52ad8 (size 16, src\main.cpp:74)
[QxOrm] **** 1 memory leaks found **** 

* ------------------------------------------------------------------------------
* 5- ./export_drugs.xml file created by the program
* ------------------------------------------------------------------------------


quick_sample.export_drugs.xml

Tutorial: qxBlog Project

In this tutorial, we will see a lot of functionalities of QxOrm library with the creation of a C++ project: qxBlog - blog management in C++.

qxBlog tutorial step by step:

  1. qxBlog project - blog management in C++
  2. All files in qxBlog project
  3. qxBlog.pro file
  4. export.h file
  5. precompiled.h file
  6. author.h and author.cpp (relationship one-to-many)
  7. comment.h and comment.cpp (relationship many-to-one)
  8. category.h and category.cpp (relationship many-to-many)
  9. blog.h and blog.cpp (relationship one-to-many, many-to-one and many-to-many)
  10. main.cpp file
  11. Relationship one-to-one with person class

1- qxBlog project - blog management in C++

  • blog: 1 blog is written by 1 author, can have many comments and can be put inside many categories
  • author: 1 author can write many blogs
  • comment: 1 comment belongs to 1 blog
  • category: 1 category contains many blogs

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 the folder ./test/qxBlog/ of your QxOrm directory.
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, 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 Windows DLL 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
C++
#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.

C++
#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 blogs: We will see how to use relationship one-to-many.
In the database, there are 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 belongs 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 (using boost library), and a list of author (using qx::QxCollection of QxOrm library).
author class needs 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.

C++
#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;
// -- constructor, 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 <QxMemLeak.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 comments: we will see how to use relationship many-to-one.
In the database, there are 2 tables:

qxBlog.table.comment

Like author class, we define 2 typedefs: a smart-pointer to a comment object (using boost library) and a list of comments (using Qt library).

C++
#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;
// -- constructor, 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 <QxMemLeak.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 blogs and 1 blog can be put inside many categories: we will see how to use relationship many-to-many.
This kind of relationship needs a new table in the database to save the list of ids for each relationship.
So in the database, there are 3 tables:

qxBlog.table.category

Like author class and comment class, we define 2 typedefs: a smart-pointer to a category object (using Qt library) and a list of categories (using QxOrm library).

C++
#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;
// -- constructor, 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 <QxMemLeak.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 comments and can be put inside many categories.
So this class has 3 relationships: one-to-many, many-to-one et many-to-many.
Like other classes, we define 2 typedefs: a smart-pointer to a blog object (using boost library) and a list of blogs (using stl library).

C++
#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;
// -- constructor, 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 <QxMemLeak.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 also provides 2 other important functionalities:

  • Serialization: Binary and XML format
  • Reflection: Access to classes definitions, retrieve properties and call classes methods
C++
#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 <QxMemLeak.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 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 connection 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 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...

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 are 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 children (of type person): this is a relationship one-to-many on the same table person.

History

Changes in version 1.4.6

  • New QxHttpServer module : C++/Qt standalone multi-threaded HTTP 1.1 web server (support SSL/TLS, persistent connections, cookies, sessions, chunked responses, URL dispatcher/routing, no other dependency except QtNetwork) : https://www.qxorm.com/qxorm_en/manual.html#manual_96
  • New QxRestApi module : provide a REST API to send requests in JSON format from external application (web services), from web-site (written in Angular for example), from QML or from scripting langage (like Python) : https://www.qxorm.com/qxorm_en/manual.html#manual_97
  • With QxHttpServer and QxRestApi modules, QxOrm library can now be used to create web applications, especially single-page applications (SPA) with famous Javascript frameworks like AngularJS, React, Meteor.js, etc...
  • New project example named qxBlogRestApi : QML application with a list of REST requests to show how to send JSON queries from Javascript to QxRestApi module + HTTP web server application to show how to create web applications using QxHttpServer module
  • QxRestApi module supports : all CRUD operations, complex queries, several levels of relationships, custom JSON output format, call dynamically native C++ functions registered in QxOrm context, instance validation, call custom database queries
  • Improve JSON serialization engine : possibility to define a custom filter to not export all properties (https://www.qxorm.com/qxorm_en/manual.html#manual_606)
  • Possibility to define a custom SQL table alias for complex queries with relationships using syntax <my_table_alias> (https://www.qxorm.com/qxorm_en/manual.html#manual_3850)
  • Improve SQL generator for Oracle database : manage last insert id using RETURNING INTO syntax (thx to Romain Macureau and Abdennour Boutrig)
  • Fix an issue with stored procedure and output parameters
  • New function available : qx::dao::count_with_relation<t>()
  • Fix JSON serialization in multi-thread environment
  • Change JSON QDateTime and QTime serialization format : use Qt::ISODateWithMs instead of Qt::ISODate (Qt 5.8 or +)
  • Improve QxService module : support SSL/TLS secure connections + keep-alive connections
  • Remove *.suo files (MSVC++ temporary project files) from QxOrm package

Changes in version 1.4.5

  • Support MongoDB database : QxOrm library becomes a C++/Qt Object Document Mapper ODM library !
  • For more details about MongoDB integration, see QxOrm manual (https://www.qxorm.com/qxorm_en/manual.html#manual_95) and new sample project available in ./test/qxBlogMongoDB/ directory
  • QxOrm library is now available on GitHub (official repository) : https://github.com/QxOrm/QxOrm
  • Fix an issue in qx::IxSqlQueryBuilder class when QxOrm library is used in a multi-thread environment
  • Support latest version of boost (1.66)
  • Update boost portable binary serialization classes to version 5.1 (provided by https://archive.codeplex.com/?p=epa)
  • Fix an issue building SQL query for Oracle database (doesn't support AS keyword for table alias)
  • Improve qx::QxClassX::registerAllClasses() function : possibility to initialize all relations (useful to work with introspection engine)
  • Improve qx::IxPersistable interface : provide new methods toJson() / fromJson()
  • Improve documentation/website : change http://www.qxorm.com by https://www.qxorm.com everywhere
  • Fix fetching relations with soft delete putting SQL condition in the JOIN part instead of WHERE part
  • Fix SQL generator for Oracle database : use new limit/pagination syntax (version Oracle > 12.1)
  • Improve SQL generator interface : add 'onBeforeSqlPrepare()' method to modify/log SQL queries in custom classes
  • Add an option in qx::QxSqlDatabase class to format SQL query (pretty-printing) before logging it (can be customized creating a qx::dao::detail::IxSqlGenerator sub-class)
  • Fix an issue with boost/std::optional (to manage NULL database values) and some databases : if optional is empty, then create a NULL QVariant based on QVariant::Type
  • Add an option in qx::QxSqlDatabase class to insert square brackets (or any other delimiters) in SQL queries for table name and/or column name (to support specific database keywords)
  • Improve introspection engine : add getType() method in qx::IxDataMember interface to get C++ type of a property dynamically
  • Improve qx::QxSqlDatabase singleton settings class to make easier working with several databases : now there are 3 levels of settings : global >> per thread >> per database (see 'bJustForCurrentThread' and 'pJustForThisDatabase' optional parameters in all setXXXX() methods)
  • Fix QxOrm.pri for MinGW compiler on Windows : an issue could occurred to export some symbols from shared library (some Qt signals for example)
  • Add an option in qx::QxSqlDatabase singleton class to display only slow SQL queries (see setTraceSqlOnlySlowQueriesDatabase() and setTraceSqlOnlySlowQueriesTotal() methods)

Changes in version 1.4.4

QxOrm library doesn't depend on boost framework anymore (the boost dependency has been fully removed, replaced by some C++11 features). So QxOrm library is now a pure Qt library which depends only on QtCore and QtSql by default. For backward compatibility, QxOrm library still supports some boost classes (boost smart-pointers, unordered containers, boost::optional, etc...) : you have to define _QX_ENABLE_BOOST compilation option to enable these features.

Main advantages are :

  • QxOrm becomes a much lighter library
  • easier to install (because you don't have to deal with boost anymore)
  • reduce compilation times
  • reduce output binary size

Thx also to Jimmy Taker for several improvments and new features in QxModelView module !

  • QxOrm library now requires a C++11 compiler (please note that QxOrm doesn't require a full compliant C++11 compiler : for example, QxOrm can be built and used with MSVC 2012, GCC 4.5 or Clang 3.2)
  • Implement PIMPL idiom for some QxOrm classes to reduce compilation times and output binary size
  • New class named qx::any to replace boost::any (basic implementation of boost::any written by Kevlin Henney)
  • qx_shared_ptr alias doesn't exist anymore : it is replaced everywhere by std::shared_ptr
  • QxModelView module : all models based on qx::IxModel class can now be sorted (on all columns), please note that you can also use QSortFilterProxyModel Qt class to sort your model
  • QxModelView module - qx::QxModel : fix setData() with e_auto_update_on_field_change option when an error occurred saving data in database, now previous value is restored if an error occurred
  • QxModelView module - qx::IxModel : fix setHeaderData() using it with default role (Qt::EditRole) changes the header in a header view (role Qt::DisplayRole)
  • QxModelView module - qx::IxModel : if a description is registered in QxOrm context, then it is displayed in header for each property
  • QxModelView module : new feature available to add automatically an empty row at the end of the table to insert quickly new items (setShowEmptyLine() method)
  • QxModelView module : possibility to define an intermediate base class between qx::IxModel and qx::QxModel to provide your own model features, for example imagine you develop a drag/drop feature in a class named IxModelDragDrop, you can now create a QxOrm model like this (see the second template parameter) : qx::IxModel * pModel = new qx::QxModel<MyPersistantClass, IxModelDragDrop>()
  • QxOrm.pro : fix DESTDIR parameter on Windows
  • QxOrm.pri and QxOrm.cmake : add a section to enable QT_USE_QSTRINGBUILDER to optimize QString operations
  • QxOrm library is now tested with MSVC 2015 compiler (support all MSVC versions from 2012)
  • Fix a bug in QxSqlError.h file with a qPrintable() call on a temporary object
  • Provide more details in logs after executing a SQL query : time to execute query in database + time to fetch C++ instances
  • Support std::optional<T> (if your compiler supports C++17 features) to manage NULL database value : new header available named <QxExtras/QxStdOptional.h> to include just after <QxOrm.h> header file (ideally in a precompiled header)

Changes in version 1.4.3

  • Support CMake : new CMakeLists.txt file added to build QxOrm library with CMake ;
  • Improve SQL error messages when qx::dao functions return a database error ;
  • New parameter in singleton class qx::QxSqlDatabase to log SQL bound values (setTraceSqlBoundValues) : by default, bound values are logged when an error occurred ;
  • New syntax to select columns to not fetch : -{ col_1, col_2, etc... } ;
  • New function qx::dao::call_query_without_prepare() to execute specific SQL queries without prepared statement ;
  • Improve QxModelView module : all QxOrm models (based on qx::IxModel interface) can be serialized to JSON format (including all relationships levels) : this is now another way to work with relationships and QML (thanks to JSON.parse() and JSON.stringify() javascript functions) without using nested models concept (so without using QxEntityEditor model/view generated classes) ;
  • Improve qxBlogModelView sample project and QxOrm manual to show how to access to relationships data in QML (nested models or JSON) ;
  • Fix a memory leak in qx::QxSqlRelation class ;
  • Reduce output binary size (~20%) and compilation times (~20%) to build persistent classes based on QxOrm library ;
  • Support unity build concept to reduce compilation times to build QxOrm library and C++ persistent classes generated by QxEntityEditor application : for more details, see _QX_UNITY_BUILD compilation option in QxOrm.pri or QxOrm.cmake configuration file
  • Improve QxConvert module : possibility to store in database complex QVariant properties which contain QVariantMap, QVariantHash or QVariantList types (JSON format)
  • Fix an issue with some databases when a foreign key is also a part of the primary key ;
  • Fix an issue with QSharedPointer and boost::serialization when a same raw pointer is shared by several QSharedPointer during deserialization process.

Changes in version 1.4.2

  • Support JSON serialization : each C++ class registered in QxOrm context can be serialized/deserialized in JSON format (JSON feature requires Qt5) ;
  • For more details about JSON serialization, read QxOrm manual here : http://www.qxorm.com/qxorm_en/manual.html#manual_606 ;
  • With JSON serialization and QxService module : it is now possible to create REST Web Services to send data to a javascript engine (web pages for example) ;
  • Fix some compilation errors with recent (and less permissive) compilers and latest versions of boost and Qt ;
  • Fix relationship initialization assertion with complex, deep and circular relationships in large database schema ;
  • Improve QDataStream serialization : should be faster now and fix an issue with circular instances dependencies ;
  • Fix a bug fetching 1-n and n-n relationships when root is a container of stack objects (it worked only with pointers or smart-pointers, for example : QList<blog> vs QList<std::shared_ptr<blog>>) ;
  • Improve qx::dump() function : possibility to display a C++ instance state in XML or JSON format.

Changes in version 1.4.1

!!! IMPORTANT NOTE ABOUT THIS VERSION !!! : it is strongly recommended to read the QxOrm.pri configuration file of this new version (compilation options have changed compared to previous versions). Now, by default, QxOrm library is a much lighter library : QxOrm depends only on QtCore and QtSql (boost serialization is now optional and not required by default). By default, serialization engine is now based on Qt QDataStream class (but you can still enable boost serialization defining _QX_ENABLE_BOOST_SERIALIZATION compilation option in QxOrm.pri configuration file). So now, with default options :

  • QxOrm 1.4.1 is much easier to install because you don't have to deal with boost serialization extra dependency ;
  • QxOrm 1.4.1 shared library is 3X smaller than 1.3.2 version ;
  • Generated binaries which depends on QxOrm library are 25% smaller ;
  • If you are not using serialization functions in current projects based on QxOrm library, then you can define or not _QX_ENABLE_BOOST_SERIALIZATION compilation option without changing any line of your source code.

Here are all other changes of version 1.4.1:

  • Improve relationships engine : possibility to select columns to fetch using syntax : my_relation { col_1, col_2, etc... } ;
  • Improve QxTraits module to reduce compilation times and build smaller binaries ;
  • Improve QxOrm website adding possibility to search and replacing the old FAQ by a more organized manual (user guide) ;
  • New compilation option _QX_ENABLE_BOOST_SERIALIZATION to enable boost serialization dependency (read QxOrm.pri configuration file for more details) ;
  • New compilation option _QX_ENABLE_QT_NETWORK to enable QxService module (transfer persistent layer over network) : read QxOrm.pri configuration file for more details ;
  • New compilation option _QX_NO_RTTI to build QxOrm library without C++ RTTI type information ;
  • Support QDataStream Qt serialization engine (used by default when _QX_ENABLE_BOOST_SERIALIZATION compilation option is not defined) ;
  • Improve qx_query class (SQL queries) : new method (named customOperator()) which gives the possibility to define a custom operator (for example for PostgreSQL ltree type) ;
  • Fix a program startup issue due to 'static initialization order fiasco' creating singletons (it was an issue with some compilers during the shared library link process) ;
  • New namespace qx::dao::throwable : same functions as qx::dao namespace, but they throw a qx::dao::sql_error exception when a SQL error occurred (instead of returning a QSqlError instance) ;
  • Add a qAssertMsg() macro to put a more explicit error message when throwing an assertion ;
  • Include all *.inl files (template implementation) in QxOrm.pro project file : QtCreator can now index these *.inl files in its project treeview ;
  • Rename QxStringCvt to QxConvert : so if you persist custom types to database, you have to rename from QxStringCvt_FromVariant, QxStringCvt_ToVariant to QxConvert_FromVariant, QxConvert_ToVariant.

Changes in version 1.3.2

  • Support C++11 types (need to set compilation options in QxOrm.pri config file to enable these features)
  • With _QX_CPP_11_SMART_PTR compilation option : std::unique_ptr, std::shared_ptr, std::weak_ptr
  • With _QX_CPP_11_CONTAINER compilation option : std::unordered_map, std::unordered_set, std::unordered_multimap, std::unordered_multiset
  • With _QX_CPP_11_TUPLE compilation option : std::tuple

Changes in version 1.3.1

  • New class qx::QxModelService in QxModelView module to connect a Qt model to services to execute client-server requests (can be used with QML and QtWidgets views)
  • Add some useful methods to qx::IxModel class and fix several issues with the QxModelView module
  • Support last version of MinGW with large precompiled header bug : new compilation option _QX_NO_PRECOMPILED_HEADER (to enable in QxOrm.pri file)
  • Fix issue when loading several shared libraries on Windows with services registered in QxService module
  • Fix the qx::QxSqlQuery serialization process used by QxService module to send requests over network
  • Fix an issue with qx::QxCollection class when inserting an item at last position

Changes in version 1.2.9

  • Improve nested models in QxModelView module to be able to use several relationships levels in QML

Changes in version 1.2.8

  • New function qx::model_view::create_nested_model (QxModelView module) used by QxEntityEditor to manage complex data structure to work with relationships in QML views and Qt model/view architecture
  • New section in the QxOrm.pri file with some tips to reduce output binaries size
  • Fix the call of triggers to have the inserted ID inside the trigger function with PostgreSQL

Changes in version 1.2.7

  • New module QxModelView : now, all classes registered into QxOrm context can be used with Qt model/view architecture (Qt widgets and/or QML views)
  • qx::IxModel interface provides an easy way to work on QML with QxOrm library and interact with databases
  • For more details about the new module QxModelView, goto the FAQ : 'How to use QxModelView module to interact with Qt model/view architecture (Qt widgets and/or QML views) ?'
  • New function qx::dao::save_with_relation_recursive(), useful to save a full tree structure for example
  • Remove the dependency on the STL compatibility functions in Qt (QT_NO_STL), which may not be available (thanks to KDE Plasma Media Center team for the patch)
  • Support database table defined into a schema (using qx::IxDataMember::setName() function)

Changes in version 1.2.6

  • First version full compatible with QxEntityEditor application : the graphic editor for QxOrm library !
  • For more details about QxEntityEditor, go to QxOrm website : http://www.qxorm.com/
  • Thanks to the recent release of Qt 5.2, QxOrm library can now be used on Android and iOS
  • Improve relationships and triggers engine
  • Triggers onBeforeFetch() and onAfterFetch() called when fetching relationships
  • Fix release mode detection during compilation : should improve performance on some environments
  • Add serialization for QSqlError, qx::QxSqlQuery, qx::QxInvalidValue and qx::QxInvalidValueX classes

Changes in version 1.2.5

  • New license : go to download page of QxOrm website for more details
  • Support Qt5
  • New compiler supported : Clang (tested on Mac OS X)
  • Now each QxOrm version will be tested in 32-bit and 64-bit mode
  • Improve QxOrm introspection engine : possibility to register static class methods
  • Improve QxService module : now it's easy to add an authentication process on server side
  • New class qx::exception to get error code + error description with services methods throwing an exception
  • New settings available in QxOrm.pri config file (whithout changing QxConfig.h file)
  • Possibility to implement specifics database SQL functions overriding qx_query class
  • Fix an issue when fetching multiple levels of relationship and NULL pointers
  • Fix a bug with MS SQL Server database and update queries using auto-increment id

Changes in version 1.2.4

  • New relationship engine to fetch easily many levels of relationships per query
  • For more details about this new engine, goto the FAQ : 'How to use relationship engine to fetch datas from many tables ?'
  • Add 2 functions : qx::dao::execute_query and qx::dao::call_query to call a stored procedure or a custom SQL query
  • For more details about this new feature, goto the FAQ : 'How to execute a stored procedure or a custom SQL query ?'
  • Add support for boost::optional type to manage NULL database value without using QVariant type
  • New class : qx::QxDaoAsync to make easier to execute queries in asynchronous way (multi-thread)
  • For more details about this new class, goto the FAQ : 'How to use qx::QxDaoAsync class to execute queries in asynchronous way (multi-thread) ?'

Changes in version 1.2.3

  • New interface 'qx::IxPersistable' (abstract class) to simplify polymorphism using QxOrm library
  • For more details about this new interface, goto the FAQ : 'How to use qx::IxPersistable interface ?'
  • New methods into 'qx::IxCollection' interface to iterate over each items without knowing its type
  • New option into 'QxOrm.pri' file to build QxOrm library statically (see '_QX_STATIC_BUILD' option)
  • New triggers : 'qx::dao::on_before_fetch' and 'qx::dao::on_after_fetch' (for more details, goto the FAQ : 'How to define a Trigger with QxOrm ?')
  • Add 'std::type_info' class information to introspection engine
  • Some minor bugs fixed ('qx::dao::sql_error' exception message, SQL query column alias, mutex, etc.)

Changes in version 1.2.2

  • New module to provide a validation engine: QxValidator module
  • For more details about QxValidator module, goto the FAQ of QxOrm library: 'How to use QxValidator module to automatically validate an instance ?'
  • Fix last insert ID with PostgreSQL using 'RETURNING' keyword: fetch inserted ID instead of OID
  • Improve SQL generator providing the good SQL type for all databases
  • Add support for special database keywords using '[', ']' and '"' characters

Changes in version 1.2.1

  • Improve 'qx::QxSqlQuery' class: new engine to build queries without writing SQL, for more details, see the FAQ 'How to build a query without writing SQL with the class qx::QxSqlQuery?'
  • Improve 'qx::QxSession' class: provide persistent methods (CRUD) without using 'qx::dao::xxx' functions, for more details, see the FAQ 'How to use a session (qx::QxSession class) to automatically manage database transactions (using C++ RAII)?'
  • Implement 'repository' pattern to provide a common interface for persistent methods (CRUD) with 3 new classes : 'qx::IxRepository', 'qx::QxRepository<t>' and 'qx::QxRepositoryX'
  • Possibility to serialize a QVariant 'UserType' with serialization engine of QxOrm library
  • Improve thread-safe 'qx::cache': add insertion date-time into the cache to verify that an element must be updated or not, for more details, see the FAQ 'How to use the cache (functions into namespace qx::cache) of QxOrm library ?'
  • FAQ updated on QxOrm website with now 28 questions and answers

Changes in version 1.1.9

  • Possibility to register automatically Qt meta-properties (using Q_PROPERTY macro) to QxOrm context without writing mapping function per class (void qx::register_class<t>()</t><t>)
  • Strong integration with Qt introspection/moc engine : for more details about this new feature, goto the FAQ 'How to register automatically Qt meta-properties to QxOrm context ?'
  • Improve introspection/reflection engine: see the FAQ (How to use introspection engine (or reflection engine) of QxOrm library?) for more details
  • Possibility to add meta-data (using a property bag) to introspection engine : see 'IxClass', 'IxDataMember' and 'IxFunction' classes for more details
  • Add function 'qx::QxClassX::dumpSqlSchema()' to explain how to create your own SQL schema based on C++ classes
  • New class 'qx::QxSimpleCrypt' to provide encryption/decryption (thanks very much to Andre Somers) : so it's now possible to store encrypted data into database without using an external library
  • QxService module: new feature to encrypt/decrypt data before transferring it over network

Changes in version 1.1.8

  • QxOrm library can now be used on Mac (thanks very much to Dominique Billet): see 'osx_build_all_debug.sh' and 'osx_build_all_release.sh' scripts to build QxOrm library and all samples in './test/' directory
  • Add 'qx::QxSession' class : define a session to manage automatically database transactions (using C++ RAII), see the FAQ for more details
  • Add 'qx::QxDateNeutral', 'qx::QxTimeNeutral' and 'qx::QxDateTimeNeutral' classes : helper classes to store date-time value into database under neutral format => cross database compatibility

Changes in version 1.1.7

  • Added soft delete behavior: see the FAQ (How to define a soft delete behavior?) for more details about this new feature
  • Added functions into namespace 'qx::dao' to update an element with a SQL condition: update_by_query, update_optimized_by_query, etc.
  • Fixed a bug when QVariant type is used for a property of a persistent class: so, it's now possible to insert NULL value into database

Changes in version 1.1.6

  • QxOrm library online documentation available: http://www.qxorm.com/doxygen/index.html
  • Possibility to disable QtGui dependency using compilation option in 'QxConfig.h' file: _QX_ENABLE_QT_GUI_DEPENDENCY
  • Possibility to disable QtNetwork dependency (so QxService module too) using compilation option in 'QxConfig.h' file: _QX_ENABLE_QT_NETWORK_DEPENDENCY
  • Provided a new macro to register abstract class into QxOrm context: QX_REGISTER_ABSTRACT_CLASS()

Changes in version 1.1.5

  • New feature available: 'QxService' module to create C++ application server
  • 'QxService' provides an easy and powerful way to create services and to transfer data over network
  • New tutorial available to explain how 'QxService' module works
  • New sample available at './test/qxClientServer' directory
  • QxOrm can be built with 'CONFIG += no_keywords' flag in '*.pro' files
  • Bug fix with 'qx::dao::create_table<>' function and relation 'many-to-many'
  • QxOrm should now build fine with GCC <= 4.2

Changes in version 1.1.4

  • New parameter in functions 'qx::dao::fetch_by_id', 'qx::dao::fetch_all', 'qx::dao::fetch_by_query' and 'qx::dao::update' to define a list of properties to fetch/update (by default, all properties are fetched/updated)
  • Support multi-columns primary key (composite key): see sample './test/qxBlogCompositeKey/'
  • Improved strategy of inheritance: QxOrm supports 'Concrete Table Inheritance' strategy ('Concrete Table Inheritance' becomes default strategy)
  • New smart-pointer 'qx::dao::ptr<t>' based on Qt 'QSharedPointer<t>' to provide 2 new features: 'is dirty' and 'update optimized'
  • 'qx::dao::ptr<t>' can be used with a simple object and with many containers (stl, boost, Qt and 'qx::QxCollection' containers)
  • 'qx::dao::ptr<t>' keeps original values from database and provides a 'isDirty()' method to retrieve all properties changed
  • 'qx::dao::update_optimized' must be used with 'qx::dao::ptr<t>' to save into database only properties changed

Changes in version 1.1.3

  • This version works fine with MinGW on Windows

Changes in version 1.1.2

  • License LGPL
  • Fixed compilation problems on Linux and boost > 1.38
  • Fixed SQL query with MySql database
  • Disabled assert when qx::dao functions return an error

Changes in version 1.1.1

  • This version supports Visual Studio 2010

Changes in version 1.1.0

  • First release

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)