It is the ORM library of QE Framework. It allows you to map QObjects in memory to a relational database. The main target is to provide a FREE and open-source ORM over Qt.
Let's go through an example to learn how to use QEOrm library.
QEOrm uses QObject's properties and their annotations (see QEAnnotation library). Let's assume we have a 'Book' class and we want to store it into DB:
class Book : public QObject
{
Q_OBJECT
Q_CLASSINFO( "class", "@qe.model.name=book")
Q_PROPERTY( int id MEMBER id)
Q_CLASSINFO( "id", "@qe.entity.isAutoIncrementable=true @qe.entity.name=bid")
Q_PROPERTY( QString title MEMBER title)
Q_CLASSINFO( "title", "@qe.entity.maxLength=256")
Q_PROPERTY( QString author MEMBER author)
Q_CLASSINFO( "author", "@qe.entity.maxLength=512")
public:
int id = 0;
QString title;
QString author;
};
Using those annotations, QEOrm will create (if it does not exist yet) a DB schema:
- Table name will be book, as we indicated using @qe.model.name.
- This table will contain 3 fields:
- bid field is an integer, primary key and auto_increment. When you mark the property as isAutoIncrementable=true and there is no primary key, it will become the primary key. In this example, we can also see a name mapping between property name (id) to column name (bid) using @qe.entity.name annotation.
- title field is a text column which maximum length is 256. The real type depends of the used DB. On SQLite, it will be 'TEXT', but in MySQL it could be 'VARCHAR'.
- author field is also a text column which maximum length is 512.
Insertion and update uses the same function: QEOrm::instance().save(...). You have to setup the default database before use this function. You are also able to use a custom database connection using SerializedItem object to indicate the name of the connection.
But let's see an example:
Book b1;
b1.id = 0;
b1.title = "Effective Modern C++";
b1.author = "Scott Meyers";
QEOrm::instance().save( &b1);
// b1.id is automatically updated!!!
if( b1.id == 0)
qCritical() << "Error: Book is NOT saved into DB";
b1.title = "Effective Modern C++ 11";
QEOrm::instance().save( &b1);
// b1 is updated !!!
In order to load an object, you will need to know the values of the primary key:
Book b2;
QEOrm::instance().load( {b1.id}, &b2);
if( b1 != b2)
qCritial() << "Error!!!";
In order to create and load objects in memory, the target class MUST have at least one invokable constructor (using Q_INVOKABLE Qt macro) and a QObject pointer as parent object as usual in Qt.
class PersonInfo : public QObject
{
Q_OBJECT
// Id property is the primary key on DB and auto_increment.
Q_PROPERTY( int id MEMBER m_id)
Q_CLASSINFO( "id", "@qe.entity.isAutoIncrementable=true")
// Name property is NOT null and max size is 256.
Q_PROPERTY( QString name MEMBER m_name)
Q_CLASSINFO( "name", "@qe.entity.maxLength=256 @qe.entity.isNullable=false)
public:
// Invokable constructor with, at least, QObject* as first argument.
Q_INVOKABLE PersonInfo( QObject* parent = nullptr, QString name = QString());
// ...
};
The below table shows the available annotations on QEOrm library:
Annotation | Scope | Description |
---|---|---|
@qe.model.name | class | DB table name. By default, class name will be used. |
@qe.entity.primaryKey | class | A comma-separated list of property names which compose the primary key. By default, it is empty. |
@qe.entity.name | property | DB column name. By default, property name will be used. |
@qe.entity.isEnable | property | If it is false, that property will NOT be exported into DB. By default, it is true. |
@qe.entity.maxLength | property | In array types (like varchar, char, etc.) it sets the maximum size constraint. By default, it is 0 and means no constraint. |
@qe.entity.isParentExported | class | If it is true, parent class properties will be also exported. By default, it is false. |
@qe.entity.isNullable | property | It indicates if DB column could be null. By default, it is true |
@qe.entity.isAutoIncrementable | property | It marks its DB column as auto_increment field. Due to some DB constraints, this field should be only one, integer type and it will become a primary key if no other entity has been marked as primary key. |
@qe.entity.mapping.type | property | It refers the type of the relation. See Relations One to Many |
@qe.entity.mapping.entity | property | It sets the target entity in the relation. See Relations One to Many |
TODO, but you can see an example in source code of tests. There is a lot of pending-work here... I know, but step by step.
Enum types are supported from Qt 5.5.0 version and it requires the use of Q_ENUM in the definition of the type. You can see an example in source code of tests.
The easiest way to use this library in your code is by Conan Package Manager. Please use the project setup that you can find in QEOrm/1.0.0 Conan.
If you use CMake, the steps after adding this dependency to your "conanfile.py" are as usual:
$~/yourProject > mkdir build
$~/yourProject > cd build
$~/yourProject/build > conan install -s build_type=debug ..
$~/yourProject/build > cmake -DCMAKE_BUILD_TYPE=Debug ..
$~/yourProject/build > cmake --build .
This library uses Semantic Versioning and internal private implementation to provide a long-term, stable, and reusable binaries.
This license follows the dual-license pattern that Qt is currently using. A LGPL 3.0 license for projects that do not need commercial support, and another one, Commercial license for rest of cases.
You can find a brief comparison between both licenses in the below table:
License types | LGPLv3 | Commercial |
---|---|---|
Community Support | Yes | Yes |
Official Support Helpdesk | No | Yes |
Keep your application private | No | Yes |
Possible to keep your application private with dynamic linking | Yes | Yes |
No need to provide a relinking mechanism for QE Framework (can always use static linking) |
No | Yes |
No need to provide a copy of license and explicitly acknowledge the use of QE |
No | Yes |
No need to make copy of the QE Framework source code available for customers |
No | Yes |
Full rights to proprietary QE source code modifications | No | Yes |
Enforce DRM | See LGPLv3 FAQ | Yes |
Enforce software patents | See LGPLv3 FAQ | Yes |