QxOrm入门实战

本文档详细介绍了QxOrm入门实战,通过一个名为BlogDemo的项目,展示了如何创建表格、初始化数据库、插入、删除、修改数据、查询数据以及使用事务和软触发器。每个关键步骤都配以代码示例,包括作者、博客、评论和分类的模型定义,以及数据库操作的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

QxOrm入门实战

博客例程 – BlogDemo项目

外键统一使用QSharedPointer智能指针

1 创建表格

  • 博客:一个博客由一个作者编写,可以有多个评论,并可以放置在多个分类中。

    Blog.h

    #ifndef BLOG_H
    #define BLOG_H
    
    #include "Author.h"
    #include "Category.h"
    #include "Comment.h"
    
    class BLOG_DLL_EXPORT Blog {
     public:
      Blog() : m_id(0) {}
      virtual ~Blog() {}
    
     public:
      long m_id;                          //主键
      QString m_title;                    //标题
      QString m_text;                     //内容
      QDateTime m_createdAt;              //创建时间
        
      AuthorPtr m_authorPtr;              //作者
      CommentPtrVect m_commentPtrVect;    //评论列表
      CategoryPtrColl m_categoryPtrColl;  //标签列表
    };
    
    typedef QSharedPointer<Blog> BlogPtr;
    
    /************************************************************
     * QX_REGISTER_HPP_APP 宏是必须的,用于将 Blog 类注册到 QxOrm 的上下文中
     * 参数一:表示要注册的当前类 - Blog
     * 参数二:基类,如果没有基类,则使用 qx::trait::no_base_class_defined
     * 参数三:用于序列化的类版本
     * ***********************************************************/
    QX_REGISTER_HPP_BLOG(Blog, qx::trait::no_base_class_defined, 0)
    
    #endif  // BLOG_H
    

    Blog.cpp

    #include "Blog.h"
    
    #include <QxOrm_Impl.h>
    
    #include "precompiled.h"
    
    /************************************************************
     * QX_REGISTER_CPP_BLOG 宏是必须的,用于将 Blog 类注册到 QxOrm 的上下文中
     * ***********************************************************/
    QX_REGISTER_CPP_BLOG(Blog)
    
    namespace qx {
     /**************************************************************
     * qx::register_class() 是一个设置函数
     * 用于将 User 类对应的属性 注册到 QxOrm 的上下文中
     * ***********************************************************/
    template <> void register_class(QxClass<Blog>& t) {
      //设置数据库表名
      t.setName("t_blog");
        
      //设置表的主键
      t.id(&Blog::m_id, "id");
    
      //添加字段
      t.data(&Blog::m_title, "title");
      t.data(&Blog::m_text, "text");
      t.data(&Blog::m_createdAt, "created_at");
    
      //创建一个n-1的关联关系,并添加字段 author_id ,此字段作表Author的外键
      t.relationManyToOne(&Blog::m_authorPtr, "author_id");
      
      //创建一个1-n的关联关系,关系名为 list_comment,(表Comment 的字段 blog_id 作为此表的外键)
      t.relationOneToMany(&Blog::m_commentPtrVect, "list_comment", "blog_id");
        
      //创建一个n-n的关联关系,关系名为 list_blog,取用时是blog_id->category_id的映射
      //创建一个新表 category_blog(如果不存在),并添加字段category_id和blog_id
      t.relationManyToMany(&Blog::m_categoryPtrColl, "list_category",
                           "category_blog", "blog_id", "category_id");
    }
    }  // namespace qx
    
  • 作者:一个作者可以编写多个博客

    Author.h

    #ifndef AUTHOR_H
    #define AUTHOR_H
    
    class Blog;
    
    typedef QSharedPointer<Blog> BlogPtr;
    typedef QVector<BlogPtr> BlogPtrVect;
    
    class BLOG_DLL_EXPORT Author {
     public:
      enum Sex { Male, Female, Unknown };
    
     public:
      Author() : m_id(0), m_sex(Unknown) {}
      ~Author() {}
      int age() const;
    
     public:
      long m_id;                  //主键
      Sex m_sex;                  //性别
      QString m_name;             //姓名
      QDate m_birthdate;          //出生日期
      BlogPtrVect m_blogPtrVect;  //博客列表
    };
    
    typedef QSharedPointer<Author> AuthorPtr;
    QX_REGISTER_HPP_BLOG(Author, qx::trait::no_base_class_defined, 0)
    
    #endif  // AUTHOR_H
    
    

    Author.cpp

    #include "Author.h"
    
    #include <QxOrm_Impl.h>
    
    #include "Blog.h"
    #include "precompiled.h"
    
    QX_REGISTER_CPP_BLOG(Author)
    
    namespace qx {
    template <> void register_class(QxClass<Author> &t) {
      t.setName("d_author");
    
      t.id(&Author::m_id, "id");
    
      t.data(&Author::m_sex, "sex");
      t.data(&Author::m_name, "name");
      t.data(&Author::m_birthdate, "birthdate");
    
      //创建一个1-n的关联关系,关系名为 list_blog,(表Blog 的字段 author_id 作为此表的外键)
      t.relationOneToMany(&Author::m_blogPtrVect, "list_blog", "author_id");
    
      //注册一个没有参数的方法
      t.fct_0<int>(&Author::age, "age");
    }
    }  // namespace qx
    
    int Author::age() const {
      if (!m_birthdate.isValid()) {
        return -1;
      }
      return (QDate::currentDate().year() - m_birthdate.year());
    }
    
    
  • 评论:一个评论属于一个博客

    Comment.h

    #ifndef COMMENT_H
    #define COMMENT_H
    
    class Blog;
    
    class BLOG_DLL_EXPORT Comment {
     public:
      typedef QSharedPointer<Blog> BlogPtr;
    
     public:
      Comment() : m_id(0) {}
      virtual ~Comment() {}
    
     public:
      long m_id;
      QString m_text;
      BlogPtr m_blogPtr;
      QDateTime m_createdAt;
    };
    
    typedef QSharedPointer<Comment> CommentPtr;
    typedef QVector<CommentPtr> CommentPtrVect;
    
    QX_REGISTER_HPP_BLOG(Comment, qx::trait::no_base_class_defined, 0)
    
    #endif  // COMMENT_H
    

    Comment.cpp

    #include "Comment.h"
    
    #include <QxOrm_Impl.h>
    
    #include "Blog.h"
    #include "precompiled.h"
    
    QX_REGISTER_CPP_BLOG(Comment)
    
    namespace qx {
    template <>
    void register_class(QxClass<Comment>& t) {
      t.setName("d_comment");
    
      t.id(&Comment::m_id, "id");
    
      t.data(&Comment::m_text, "text");
      t.data(&Comment::m_createdAt, "created_at");
    
      //创建一个n-1的关联关系,并添加字段 blog_id ,此字段作表Comment的外键
      t.relationManyToOne(&Comment::m_blogPtr, "blog_id");
    }
    }  // namespace qx
    
  • 分类:一个分类包含多个博客

    Category.h

    #ifndef CATEGORY_H
    #define CATEGORY_H
    
    class Blog;
    
    class BLOG_DLL_EXPORT Category {
     public:
      typedef QSharedPointer<Blog> BlogPtr;
      typedef qx::QxCollection<long, BlogPtr> BlogPtrColl;
    
     public:
      Category() : m_id(0) {}
      virtual ~Category() {}
    
     public:
      long m_id;                  //主键
      QString m_name;             //名字
      QString m_desc;             //描述
      BlogPtrColl m_blogPtrColl;  //博客列表
    };
    
    typedef QSharedPointer<Category> CategoryPtr;
    typedef qx::QxCollection<long, CategoryPtr> CategoryPtrColl;
    
    QX_REGISTER_HPP_BLOG(Category, qx::trait::no_base_class_defined, 0)
    
    #endif  // CATEGORY_H
    

    Category.cpp

    #include "Category.h"
    
    #include <QxOrm_Impl.h>
    
    #include "Blog.h"
    
    QX_REGISTER_CPP_BLOG(Category)
    
    namespace qx {
    template <>
    void register_class(QxClass<Category>& t) {
      t.setName("t_category");
    
      t.id(&Category::m_id, "id");
    
      t.data(&Category::m_name, "name");
      t.data(&Category::m_desc, "description");
        
      //创建一个n-n的关联关系,关系名为 list_blog,取用时是category_id->blog_id的映射
      //创建一个新表 category_blog(如果不存在),并添加字段category_id和blog_id
      t.relationManyToMany(&Category::m_blogPtrColl, "list_blog", "category_blog",
                           "category_id", "blog_id");
    }
    }  // namespace qx
    

2 数据库初始化

  • 连接到数据库,默认连接一个

    qx::QxSqlDatabase::getSingleton()->setDriverName("QSQLITE");
    qx::QxSqlDatabase::getSingleton()->setDatabaseName("./blogDemo.db");
    qx::QxSqlDatabase::getSingleton()->setHostName("localhost");
    qx::QxSqlDatabase::getSingleton()->setUserName("root");
    qx::QxSqlDatabase::getSingleton()->setPassword("");
    
    //设置 SQL 查询中的占位符风格为 ph_style_2_point_name。这是一种特定的占位符风格,用于在 SQL 查询中指定参数。
    qx::QxSqlDatabase::getSingleton()->setSqlPlaceHolderStyle(qx::QxSqlDatabase::ph_style_2_point_name);
    //开启 SQL 查询的追踪功能。这意味着在执行 SQL 查询时将输出相关的跟踪信息,如查询语句、参数值等。
    qx::QxSqlDatabase::getSingleton()->setTraceSqlQuery(true);
      
    //获取到db
    QSqlDatabase db =  qx::QxSqlDatabase::getSingleton()->getDatabase();
    
  • 多个数据库连接,每一个操作后面都有一个参数可以指定数据库

    // 数据库一,该方式为创建默认数据库
    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("12345678");
    
    // 数据库二
    QSqlDatabase db2 = QSqlDatabase::addDatabase("QSQLITE"); //定义全局的,此处只是举例
    db2.setDatabaseName("./Users2.db");
    
    // 数据库三
    QSqlDatabase db3 = QSqlDatabase::addDatabase("QSQLITE"); //定义全局的,此处只是举例
    db3.setDatabaseName("./Users3.db");
    
    //创建表
    qx::dao::create_table<Author>();      //数据库一创建表(默认)
    qx::dao::create_table<Author>(&db2);  //数据库二创建表
    qx::dao::create_table<Author>(&db3);  //数据库三创建表
    
    //删除表
    QSqlError daoError = qx::dao::delete_all<Author>();(默认)
    daoError = qx::dao::delete_all<Author>(&db2);
    daoError = qx::dao::delete_all<Author>(&db3);
    daoError = qx::dao::delete_all<Author>(&db4);
    
  • 创建表

    QSqlError daoError = qx::dao::create_table<Author>();
    daoError = qx::dao::create_table<Comment>();
    daoError = qx::dao::create_table<Blog>();
    daoError = qx::dao::create_table<Category>();
    

3 插入数据

  • 创建3个作者

    AuthorPtr author1(new Author());
    AuthorPtr author2(new Author());
    AuthorPtr author3(new Author());
    
    author1->m_id = 1;
    author1->m_name = "sjl";
    author1->m_sex = Author::Male;
    author1->m_birthdate = QDate(2000, 01, 01);
    
    author1->m_id = 2;
    author2->m_name = "jls";
    author2->m_sex = Author::Male;
    author2->m_birthdate = QDate(2010, 01, 01);
    
    author1->m_id = 3;
    author3->m_name = "ljs";
    author3->m_sex = Author::Female;
    author3->m_birthdate = QDate(2009, 01, 01);
    
    QVector<AuthorPtr> authorVect;
    authorVect << author1 << author2 << author3;
    
    daoError = qx::dao::insert(authorVect);		//一次性插入3条数据
    qDebug() << qx::dao::count<Author>();		//获取当前表数据条数:SELECT COUNT(*) FROM d_author
    
  • 创建1个博客

    BlogPtr blogptr1(new Blog());
    BlogPtr blogptr2(new Blog());
    
    blogptr1->m_title = QObject::tr("m_titlem_titlem_titlem_title");
    blogptr1->m_text = QObject::tr("m_textm_textm_tm_textm_textm_textm_text");
    blogptr1->m_createdAt = QDateTime::currentDateTime();
    blogptr1->m_authorPtr = author1;
    
    blogptr2->m_title = QObject::tr("1m_titlem_titlem_titlem_title");
    blogptr2->m_text = QObject::tr("2m_textm_textm_tm_textm_textm_textm_text");
    blogptr2->m_createdAt = QDateTime::currentDateTime();
    blogptr2->m_authorPtr = author2;
    
    qx::dao::insert(blogptr1);
    qx::dao::insert(blogptr2);
    
  • 同时创建1个博客,带1个作者,带2条评论

    BlogPtr blogptr1(new Blog());
    
    blogptr1->m_title = QObject::tr("m_titlem_titlem_titlem_title");
    blogptr1->m_text = QObject::tr("m_textm_textm_tm_textm_textm_textm_text");
    blogptr1->m_createdAt = QDateTime::currentDateTime();
    blogptr1->m_authorPtr = author1;
    
    //作者
    AuthorPtr author4(new Author());
    author4->m_id = 1;
    author4->m_name = "sjlsjl";
    author4->m_sex = Author::Male;
    author4->m_birthdate = QDate(2001, 02, 01);
    
    //评论
    CommentPtr commPtr1(new Comment());
    CommentPtr commPtr2(new Comment());
    
    commPtr1->m_text = QObject::tr("Comment111111111111");
    commPtr1->m_createdAt = QDateTime::currentDateTime();
    commPtr1->m_blogPtr = blogptr1;
    
    commPtr2->m_text = QObject::tr("Comment2222222222222");
    commPtr2->m_createdAt = QDateTime::currentDateTime();
    commPtr2->m_blogPtr = blogptr1;
    
    //博客
    BlogPtr blogptr2(new Blog());
    blogptr2->m_title = QObject::tr("1m_titlem_titlem_titlem_title");
    blogptr2->m_text = QObject::tr("2m_textm_textm_tm_textm_textm_textm_text");
    blogptr2->m_createdAt = QDateTime::currentDateTime();
    blogptr2->m_authorPtr = author4;
    blogptr2->m_commentPtrVect << commPtr1 << commPtr2;
    
    //插入带关系的实体
    qx::dao::insert_with_all_relation(blogptr2);
    
    //下面两种插入方法和上面是同一个效果,只要with_all表全部关系
    //关系如何书写请看下面单独小节
    qx::dao::insert_with_relation("*", blogptr1);
    
    QStringList relation;relation << "*";
    qx::dao::insert_with_relation(relation, blogptr1);
    

4 删除数据

  • 删除表中全部数据

    qx::dao::delete_all<Author>();
    
  • 根据PO中的id删除数据

    AuthorPtr authorTmp(new Author());
    authorTmp->m_id = 4;
    qx::dao::delete_by_id(authorTmp);
    
  • 根据其他条件删除数据

    qx::QxSqlQuery queryTmp("WHERE d_author.sex = :sex");
    queryTmp.bind(":sex", Author::Female);
    qx::dao::delete_by_query<Author>(queryTmp);
    

5 修改数据

  • 依据PO中的id更新数据

    AuthorPtr authorTmp(new Author());
    authorTmp->m_id = 4;
    authorTmp->m_name = "Jon";
    qx::dao::update(authorTmp);
    
  • 如何存在id相同的数据就修改数据,否则插入一条新数据

    AuthorPtr authorTmp2(new Author());
    authorTmp2->m_id = 1;
    authorTmp2->m_name = "txtxtx";
    authorTmp2->m_sex = Author::Female;
    authorTmp2->m_birthdate = QDate::currentDate();
    
    qx::dao::save(authorTmp2);
    
  • 带关系的分组插入

    BlogPtr blog_1(new Blog());
    blog_1->m_title = "blog";
    blog_1->m_text = "blog1111";
    blog_1->m_authorPtr = author1;
    blog_1->m_createdAt = QDateTime::currentDateTime();
    
    //使用 'save()' 方法插入数据到数据库
    daoError = qx::dao::save(blog_1);
    
    //使用 'save()' 方法更新数据库数据
    blog_1->m_text = "txtxttxtxttxtxtxtx";
    daoError = qx::dao::save(blog_1);
    
    //插入2个分组
    blog_1->m_categoryPtrColl.insert(category1->m_id, category1);
    blog_1->m_categoryPtrColl.insert(category3->m_id, category3);
    daoError = qx::dao::save_with_relation("list_category", blog_1);
    
    //获取博客,并附带获取作者、评论、分组
    BlogPtr blogTmp(new Blog());
    blogTmp->m_id = blog_1->m_id;
    daoError = qx::dao::fetch_by_id_with_all_relation(blogTmp);
    
    qDebug() << "m_commentPtrVect" << blogTmp->m_authorPtr->m_name;
    qDebug() << "m_commentPtrVect" << blogTmp->m_commentPtrVect.size();
    qDebug() << "m_commentPtrVect" << blogTmp->m_categoryPtrColl.size();
    

6 查询数据

  • 查出全部数据

    BlogPtrVect blogPtrVect;
    daoError = qx::dao::fetch_all(blogPtrVect);
    
  • sql语句查询

    qx::QxSqlQuery query("WHERE d_author.sex = :sex");
    query.bind(":sex", Author::Female);
    QVector<AuthorPtr> authorVect2;
    daoError = qx::dao::fetch_by_query(query, authorVect2);
    
  • 组合查询(下面仅作例子参考,部分字段可能不存在)

    qx_query query;
    query.where("sex")
        .isEqualTo(User::Female)
        .and_("age")
        .isLessThan(38)
        .orderAsc("id")
        .limit(5, 5);
    
    qx_query query;     
    query.where("sex").isEqualTo(author::female)
        .and_("age").isGreaterThan(38)
        .or_("last_name").isNotEqualTo("Dupont")
        .or_("first_name").like("Alfred")
        .and_OpenParenthesis("id").isLessThanOrEqualTo(999)
        .and_("birth_date").isBetween(date1, date2)
        .closeParenthesis()
        .or_("id").in(50, 999, 11, 23, 78945)
        .and_("is_deleted").isNotNull()
        .orderAsc("last_name", "first_name", "sex")
        .limit(50, 150);
    QList<User> list_of_female;
    qx::dao::fetch_by_query(query, list_of_female);
    for (int i = 0; i < list_of_female.count(); i++)
        ;//your code
    
  • 自定义字段查询+连表查询

    BlogPtrVect blogPtrVect;
    QStringList relationList;
    relationList << "{ title, text }"				//当前表只查询title和text字段
        << "author_id { name, birthdate }"			//author表查询name和birthdate字段
        << "list_comment { text, created_at }";		//comment表查询text和created_at字段
    daoError = qx::dao::fetch_all_with_relation(relationList, blogPtrVect);
    
    qDebug() << blogPtrVect[0]->m_title
        << blogPtrVect[0]->m_text << blogPtrVect[0]->m_createdAt.isNull();
    qDebug() << blogPtrVect[0]->m_authorPtr->m_name
        << blogPtrVect[0]->m_authorPtr->m_birthdate
        << blogPtrVect[0]->m_authorPtr->m_sex;
    qDebug() << blogPtrVect[0]->m_commentPtrVect.size();
    for (int i = 0; i < blogPtrVect[0]->m_commentPtrVect.size(); i++) {
        qDebug() << blogPtrVect[0]->m_commentPtrVect[i]->m_text;
    }
    
  • 连表查询查出全部数据

    BlogPtrVect blogPtrVect;
    daoError = qx::dao::fetch_all_with_all_relation(blogPtrVect);
    

7 事务

  • 事务

    //打开数据库的事务
    QSqlDatabase db = qx::QxSqlDatabase::getDatabase();
    bool bCommit = db.transaction();
    
    daoError = qx::dao::insert(category1, (&db));
    daoError = qx::dao::insert(category2, (&db));
    daoError = qx::dao::insert(category3, (&db));
    
    qDebug() << "category1->m_id = " << category1->m_id;
    qDebug() << "category2->m_id = " << category2->m_id;
    qDebug() << "category3->m_id = " << category3->m_id;
    
    //事务提交或者回滚
    if (bCommit) {
        db.commit();
    } else {
        db.rollback();
    }
    

8 软触发器

  • 基础Po类:为子类提供统一的字段与回调

    APo.h

    #ifndef _QX_APO_H_
    #define _QX_APO_H_
    
    class BIO_DLL_EXPORT APo : public qx::IxPersistable {
      QX_REGISTER_FRIEND_CLASS(APo)
     public:
      APo() : m_id(0) {}
      virtual ~APo() {}
        
      //声明定义回调函数
      void onBeforeInsert(qx::dao::detail::IxDao_Helper* dao);
      void onBeforeUpdate(qx::dao::detail::IxDao_Helper* dao);
    
     public:
      long m_id;
      QDateTime m_updatedAt;
      QDateTime m_createdAt;
    };
    
    //注册一个抽象类
    QX_REGISTER_ABSTRACT_CLASS(APo)
    QX_REGISTER_HPP_BIO(APo, qx::trait::no_base_class_defined, 0)
    
    /************************************************************
     * QxDao_Trigger<APo> 是一个特化的模板结构体
     * 主要用于处理持久化操作(如插入、更新、删除、获取)的前后触发器。
     * ***********************************************************/
    namespace qx {
    namespace dao {
    namespace detail {
    
    template <>
    struct QxDao_Trigger<APo> {
      static inline void onBeforeInsert(APo* t,qx::dao::detail::IxDao_Helper* dao) {
        if (t) {t->onBeforeInsert(dao);}
      }
      static inline void onBeforeUpdate(APo* t,qx::dao::detail::IxDao_Helper* dao) {
        if (t) {t->onBeforeUpdate(dao);}
      }
      static inline void onBeforeDelete(APo* t,qx::dao::detail::IxDao_Helper* dao) {
        Q_UNUSED(t);Q_UNUSED(dao);
      }
      static inline void onBeforeFetch(APo* t, qx::dao::detail::IxDao_Helper* dao) {
        Q_UNUSED(t);Q_UNUSED(dao);
      }
      static inline void onAfterInsert(APo* t, qx::dao::detail::IxDao_Helper* dao) {
        Q_UNUSED(t);Q_UNUSED(dao);
      }
      static inline void onAfterUpdate(APo* t, qx::dao::detail::IxDao_Helper* dao) {
        Q_UNUSED(t);Q_UNUSED(dao);
      }
      static inline void onAfterDelete(APo* t, qx::dao::detail::IxDao_Helper* dao) {
        Q_UNUSED(t);Q_UNUSED(dao);
      }
      static inline void onAfterFetch(APo* t, qx::dao::detail::IxDao_Helper* dao) {
        Q_UNUSED(t);Q_UNUSED(dao);
      }
    };
    
    }  // namespace detail
    }  // namespace dao
    }  // namespace qx
    
    #endif  // APO_H
    

    APo.cpp

    #include "APo.h"
    
    QX_REGISTER_CPP_BIO(APo)
    
    namespace qx {
    template <>
    void register_class(QxClass<APo>& t) {
      IxDataMember* pData = NULL;
    
      pData = t.id(&APo::m_id, "id");
    
      pData = t.data(&APo::m_updatedAt, "updated_at");
      pData = t.data(&APo::m_createdAt, "created_at");
    }
    }  // namespace qx
    
    /*
    	回调函数的实现
    	这里实现的功能是
    		1.插入之前将字段m_updatedAt和m_createdAt设置为当前时间
    		2.更新之前将字段m_updatedAt设置为当前时间
    */
    void APo::onBeforeInsert(qx::dao::detail::IxDao_Helper* dao) {
      Q_UNUSED(dao);
      m_updatedAt = QDateTime::currentDateTime();
      m_createdAt = QDateTime::currentDateTime();
    }
    
    void APo::onBeforeUpdate(qx::dao::detail::IxDao_Helper* dao) {
      Q_UNUSED(dao);
      m_updatedAt = QDateTime::currentDateTime();
    }
    
  • 子类复用:子类继承复用父类的功能和成员变量

    SettingsPo.h

    #ifndef SETTINGSPO_H
    #define SETTINGSPO_H
    
    #include "../Base/APo.h"
    
    class BIO_DLL_EXPORT SettingsPo : public APo {
      //用于将某个C++类声明为可以持久化的对象
      QX_PERSISTABLE_HPP(SettingsPo)
     public:
      SettingsPo() : APo() {}
      SettingsPo(QString parent, QString key, QString value, QString desc)
          : APo(), m_parent(parent), m_key(key), m_value(value), m_desc(desc) {}
    
     public:
      QString m_parent;  //父节点
      QString m_key;     //键
      QString m_value;   //值
      QString m_desc;    //描述
    };
    //注意这个地方第二个字段要指定基类APo
    QX_REGISTER_HPP_BIO(SettingsPo, APo, 0)
    
    #endif  // SETTINGSPO_H
    

    SettingPo.cpp

    #include "SettingsPo.h"
    #include <QxOrm_Impl.h>
    
    //用于将某个C++类声明为可以持久化的对象
    QX_PERSISTABLE_CPP(SettingsPo)
    QX_REGISTER_CPP_BIO(SettingsPo)
    
    namespace qx {
    template <>
    void register_class(QxClass<SettingsPo> &t) {
      t.setName("d_settings");
    
      t.data(&SettingsPo::m_parent, "parent");
      t.data(&SettingsPo::m_key, "key");
      t.data(&SettingsPo::m_value, "value");
      t.data(&SettingsPo::m_desc, "desc");
    }
    }  // namespace qx
    

补充

工程目录配置

TEMPLATE = app

# _BUILDING_BLOG,通过它可以知道项目是否正在编译
DEFINES += _BUILDING_BLOG

# C++11特性的支持
QMAKE_CXXFLAGS += -std=c++11

# 预编译头文件
!contains(DEFINES, _QX_NO_PRECOMPILED_HEADER) {
    PRECOMPILED_HEADER = precompiled.h
}
macx:CONFIG-=app_bundle

# QxOrm 库相关配置
include(/home/sjl/code/QxOrm_1.4.9/QxOrm/QxOrm.pri)
INCLUDEPATH += /home/sjl/code/QxOrm_1.4.9/QxOrm/include/
LIBS += -L"/home/sjl/code/QxOrm_1.4.9/QxOrm/lib"

# 设置生成的目标名称、添加依赖库
CONFIG(debug, debug|release) {
    TARGET = BlogDemod
    LIBS += -l"QxOrmd"
} else {
    TARGET = BlogDemo
    LIBS += -l"QxOrm"
}

export.h

#ifndef EXPORT_H
#define EXPORT_H

/****************************************
 * @file    Export
 * @brief   管理类、函数 ... 的导出/导入。
 * @author  sjl
 * @date    2023/06/25
 ****************************************/

#ifdef _BUILDING_BLOG
#define BLOG_DLL_EXPORT QX_DLL_EXPORT_HELPER
#else  // _BUILDING_BLOG
#define BLOG_DLL_EXPORT QX_DLL_IMPORT_HELPER
#endif  // _BUILDING_BLOG

#ifdef _BUILDING_BLOG
#define QX_REGISTER_HPP_BLOG QX_REGISTER_HPP_EXPORT_DLL
#define QX_REGISTER_CPP_BLOG QX_REGISTER_CPP_EXPORT_DLL
#else  // _BUILDING_BLOG
#define QX_REGISTER_HPP_BLOG QX_REGISTER_HPP_IMPORT_DLL
#define QX_REGISTER_CPP_BLOG QX_REGISTER_CPP_IMPORT_DLL
#endif  // _BUILDING_BLOG

#endif  // EXPORT_H

precompiled.h

#ifndef PRECOMPILED_H
#define PRECOMPILED_H

/****************************************
 * @file    Precompiled
 * @brief   预编译头文件,用于提高编译速度
 * @author  sjl
 * @date    2023/06/25
 ****************************************/

#include <QxOrm.h>

#include "export.h"

#endif  // PRECOMPLIED_H
<think>好的,用户之前问过关于C++ ORM和事务结合的问题,现在又问有没有关于QxOrm的书。我需要先确认用户的需求。用户可能正在使用QxOrm进行开发,需要学习资料,尤其是书籍。不过根据我的知识,QxOrm作为相对小众的C++ ORM框架,可能没有专门的书籍。 首先,我应该检查是否有相关书籍存在。可能需要快速搜索确认,但根据现有的信息,QxOrm的文档主要来自官方网站和社区资源。用户可能需要替代的学习材料,比如官方文档、教程或示例代码。 接下来,用户可能不满足于在线资源,希望有系统性的书籍来深入学习。但如果没有的话,应该建议其他资源,如官方文档、GitHub仓库、社区论坛等。同时,用户可能对类似的ORM框架比如ODB或SOCI更感兴趣,如果有相关书籍,可以推荐。 还需要考虑用户的背景。他们可能正在评估或开始使用QxOrm,需要全面了解其功能和最佳实践。如果书籍不存在,可能需要指导他们如何利用现有资源学习,比如通过示例项目、博客文章或视频教程。 另外,用户可能没有明确表达的是,他们可能遇到学习QxOrm的困难,或者希望有结构化的学习路径。这时候需要提供替代方案,比如结合C++ ORM通用知识和QxOrm特定文档,或者推荐其他框架的书籍作为参考。 最后,确保回答友好且有帮助,让用户知道虽然没有专门书籍,但有其他有效途径可以掌握QxOrm的使用。同时提醒他们注意框架的更新和社区动态,以防未来有新的资源出现。</think>关于QxOrm框架,目前**没有专门的中文或英文书籍**系统性地介绍其使用和原理。不过,可以通过以下资源高效学习和掌握QxOrm: --- ### 1. **官方核心资源** #### (1) 官方文档 - **QxOrm官网**:[http://www.qxorm.com/](http://www.qxorm.com/) 提供完整的API参考、快速入门指南和核心概念说明(如对象映射、事务管理、查询生成器等)。 - **GitHub仓库**:[QxOrm GitHub](https://github.com/QxOrm/QxOrm) 包含源码、示例代码和更新日志,适合深入理解实现细节。 #### (2) 示例代码 - **内置示例**:在源码的`test`或`example`目录中,提供数据库操作、模型定义、事务控制等典型场景的代码模板。 --- ### 2. **替代学习渠道** #### (1) 社区与论坛 - **Stack Overflow**:搜索`[QxOrm]`标签,查看实际开发中的问题与解决方案。 (例如:[如何定义一对一关系?](https://stackoverflow.com/questions/tagged/qxorm)) - **Qt官方论坛**:由于QxOrm依赖Qt库,可在[Qt Forum](https://forum.qt.io/)中查找相关讨论。 #### (2) 博客与技术文章 - **开发者博客**:部分开发者会分享QxOrm实践经验,例如: - *《QxOrm入门C++ ORM与Qt结合》* - *《使用QxOrm实现多层事务嵌套》* - **Medium/Dev.to**:搜索英文技术文章,了解高级用法。 --- ### 3. **相关书籍参考** 虽然无QxOrm专著,但以下书籍可补充ORM和C++数据库开发知识: 1. **《C++数据库开发实战》**(中文) - 涵盖ODB、SOCI等框架,帮助理解ORM通用设计模式。 2. **《Effective Modern C++》**(Scott Meyers) - 掌握C++11/14特性,提升QxOrm中模板和智能指针的使用效率。 3. **《Qt高级编程》**(中文) - 学习Qt的`QSqlDatabase`、`QSqlQuery`等底层机制,辅助调试QxOrm。 --- ### 4. **实战建议** 1. **从简单项目入手**: 用QxOrm实现一个增删改查(CRUD)应用,逐步加入事务、关联查询等复杂功能。 ```cpp // 示例:定义数据模型 class User { QX_REGISTER_FRIEND_CLASS(User) // 注册元信息 public: int id; QString name; // 关系定义(如一对多) QxCollection<Order> orders; }; QX_REGISTER_HPP_APP(User, qx::trait::no_base_class_defined, 1) ``` 2. **调试与日志**: 启用QxOrm的调试输出(`QX_DEBUG`),观察生成的SQL语句是否符合预期。 3. **结合Qt特性**: 利用Qt的信号槽机制,实现ORM操作与UI的异步交互。 --- ### 5. **注意事项** - **版本兼容性**:QxOrmQt版本有特定要求(如Qt5/Qt6),需注意环境配置。 - **性能优化**:复杂查询时,手动编写SQL可能比ORM生成的语句更高效。 - **社区活跃度**:QxOrm更新较慢,需关注GitHub Issues中的已知问题。 --- 如果急需系统化资料,建议以**官方文档为主**,辅以示例代码和社区讨论,逐步构建知识体系。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值