一、框架簡介
C++ 數據庫 ORM 框架比較有代表性的有兩個:ODB 和 QxOrm,若是使用 QT 開發,建議使用 QxOrm。QxOrm 幾乎支持所有的主流數據庫,比如 SQLite、MySQL、PostgreSQL、Oracle、MS SQL Server、MongoDB 等。
二、下載地址
參見 https://github.com/QxOrm/QxOrm
三、編譯說明
下載完畢之後,目錄如下:
我們重點關注 tools 文件夾,裏面存放所有版本的編譯批處理工具,如下:
這裏以編譯 DEBUG 版本的 qxorm 爲例進行講解,批處理工具爲:mingw_build_all_debug_qt5_minimal.bat(PS:上面的 **full版本需要 boost 支持,這裏不再演示,自行摸索)。
執行 mingw_build_all_debug_qt5_minimal.bat 之後,需要重點關注三個文件夾,如下:
這三個文件夾會在項目中使用。
四、使用案例
1.新建項目,在項目下新建 QxOrm 文件夾,文件夾裏存放上面三個文件夾,如下:
2.項目配置文件如下:
#-------------------------------------------------
#
# Project created by QtCreator 2020-06-30T22:46:06
#
#-------------------------------------------------
QT += core gui sql
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = ormDemo
TEMPLATE = app
# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
#通過它可以知道項目是否正在編譯
DEFINES += _BUILDING_USER
# 預編譯頭文件
!contains(DEFINES, _QX_NO_PRECOMPILED_HEADER) {
PRECOMPILED_HEADER = precompiled.h
}
# QxOrm 庫相關配置
INCLUDEPATH += $$PWD/QxOrm/include
LIBS += -L$$PWD/QxOrm/lib
# 設置生成的目標名稱、添加依賴庫
CONFIG(debug, debug|release) {
LIBS += -lQxOrmd
} else {
LIBS += -lQxOrm
}
SOURCES += \
main.cpp \
dialog.cpp \
user.cpp
HEADERS += \
dialog.h \
export.h \
precompiled.h \
user.h
FORMS += \
dialog.ui
3.export.h文件(必須)
#ifndef EXPORT_H
#define EXPORT_H
#ifdef _BUILDING_USER
#define USER_DLL_EXPORT QX_DLL_EXPORT_HELPER
#else
#define USER_DLL_EXPORT QX_DLL_IMPORT_HELPER
#endif
#ifdef _BUILDING_USER
#define QX_REGISTER_HPP_USER QX_REGISTER_HPP_EXPORT_DLL
#define QX_REGISTER_CPP_USER QX_REGISTER_CPP_EXPORT_DLL
#else
#define QX_REGISTER_HPP_USER QX_REGISTER_HPP_IMPORT_DLL
#define QX_REGISTER_CPP_USER QX_REGISTER_CPP_IMPORT_DLL
#endif
#endif // EXPORT_H
4.precompiled.h文件(必須)
#ifndef PRECOMPILED_H
#define PRECOMPILED_H
#include <QxOrm.h>
#include "export.h"
#endif // PRECOMPILED_H
5.user.h/user.cpp文件
user.h
#ifndef USER_H
#define USER_H
#include <QObject>
#include "precompiled.h"
class USER_DLL_EXPORT User
{
public:
User() : id(0) { }
virtual ~User() { }
long id;
QString name;
int age;
};
//QX_REGISTER_PRIMARY_KEY(User, QString) //主鍵不是整數類型的時候使用
/*
* 用於將 User 類註冊到 QxOrm 的上下文中:
* 參數一:表示要註冊的當前類 - User;
* 參數二:基類,如果沒有基類,則使用 qx::trait::no_base_class_defined;
* 參數三:用於序列化的類版本。
*/
QX_REGISTER_HPP_USER(User, qx::trait::no_base_class_defined, 1)
#endif // USER_H
user.cpp
#include "precompiled.h"
#include "user.h"
#include <QxOrm_Impl.h>
//和 QX_REGISTER_HPP_USER 相同,QX_REGISTER_CPP_USER 宏也是必需的,用於將 User 類註冊到 QxOrm 的上下文中。
QX_REGISTER_CPP_USER(User)
//在 user.cpp 文件中,需要實現 qx::register_class(),它是一個設置函數:
namespace qx {
template <> void register_class(QxClass<User> & t)
{
// 註冊 User::id <=> 數據庫中的主鍵
t.id(&User::id, "id");
// 註冊 User::name 屬性,使用的 key 是 name,version 是 1。
t.data(&User::name, "name", 1);
// 註冊 User::age 屬性,使用的 key 是 age。
t.data(&User::age, "age");
}
}
6.main.cpp文件
#include "precompiled.h"
#include "user.h"
/*
* QxOrm_Impl.h,它的作用是檢測內存泄露。如果使用 QxMemLeak 模塊或 boost::serialization 引擎,
* 應該在所有的 *.cpp 中包含它;否則,它便是可選的(非必須)
*/
#include <QxOrm_Impl.h>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// 初始化參數,用於和數據庫交互(sqlite)
// qx::QxSqlDatabase::getSingleton()->setDriverName("QSQLITE");
// qx::QxSqlDatabase::getSingleton()->setDatabaseName("./Users.db");
// qx::QxSqlDatabase::getSingleton()->setHostName("localhost");
// qx::QxSqlDatabase::getSingleton()->setUserName("root");
// qx::QxSqlDatabase::getSingleton()->setPassword("");
// 配置 MySQL
qx::QxSqlDatabase::getSingleton()->setDriverName("QMYSQL");
qx::QxSqlDatabase::getSingleton()->setDatabaseName("test");
qx::QxSqlDatabase::getSingleton()->setHostName("127.0.0.1");
qx::QxSqlDatabase::getSingleton()->setUserName("root");
qx::QxSqlDatabase::getSingleton()->setPassword("root");
qx::QxSqlDatabase::getSingleton()->setPort(3306);
// 在數據庫中創建 User 表
QSqlError daoError = qx::dao::create_table<User>();
// 創建 3 個用戶
// 可以使用 std 和 Qt 智能指針:std::shared_ptr、QSharedPointer 等...
typedef QSharedPointer<User> UserPtr;
UserPtr u1;
u1.reset(new User());
u1->name = "Jack Ma";
u1->age = 30;
UserPtr u2;
u2.reset(new User());
u2->name = "Pony";
u2->age = 25;
UserPtr u3;
u3.reset(new User());
u3->name = "Waleon";
u3->age = 18;
// 將所有用戶插入容器中
// 可以使用 std、boost、Qt 和 qx::QxCollection<Key,Value> 中的許多容器
typedef QVector<UserPtr> VectorUser;
VectorUser users;
users.push_back(u1);
users.push_back(u2);
users.push_back(u3);
// 將容器中的所有用戶插入到數據庫中
// p1、p2、p3 的 id 屬性會自動更新
daoError = qx::dao::insert(users);
// 修改第二個用戶的信息,並更新到數據庫中
u2->name = "Pony modified";
u2->age = 38;
daoError = qx::dao::update(u2);
// 從數據庫中刪除第一個用戶
daoError = qx::dao::delete_by_id(u1);
// 計算用戶的數量
long userCount = qx::dao::count<User>();
qDebug() << "User Count: " << userCount;
// 將 id 爲 3 的用戶取出,並傳給一個新變量
UserPtr userTmp;
userTmp.reset(new User());
userTmp->id = 3;
daoError = qx::dao::fetch_by_id(userTmp);
qDebug() << "User Tmp: " << userTmp->id << userTmp->name << userTmp->age;
#if _QX_SERIALIZE_XML
// 將容器中的用戶導出到 XML 文件中(序列化)
qx::serialization::xml::to_file(users, "./export_users.xml");
// 將 XML 中的用戶導入至新容器
VectorUser usersXmlTmp;
qx::serialization::xml::from_file(usersXmlTmp, "./export_users.xml");
#endif
#ifndef _QX_NO_JSON
// 將容器中的用戶導出到 Json 文件中(序列化)
qx::serialization::json::to_file(users, "./export_users.json");
// 將 Json 文件中的用戶導入至新容器
VectorUser usersJsonTmp;
qx::serialization::json::from_file(usersJsonTmp, "./export_users.json");
#endif
// 克隆一個用戶
UserPtr uClone = qx::clone_to_qt_shared_ptr(*u1);
qDebug() << "Clone from u1: " << uClone->id << uClone->name << uClone->age;
// 按類名(factory)創建新用戶
qx::any uAny = qx::create("User");
// 將用戶插入到 qx::cache
qx::cache::set("users", users);
// 從 qx::cache 中刪除所有元素
qx::cache::clear();
// 內存泄漏
// User *user = new User();
return a.exec();
}