sql - Qt 中的持久化类

标签 sql qt orm

我正在将一个中型 CRUD 应用程序从 .Net 移植到 Qt,并且我正在寻找一种用于创建持久性类的模式。在 .Net 中,我通常使用基本方法(插入、更新、删除、选择)创建抽象持久性类,例如:

public class DAOBase<T>
{
    public T GetByPrimaryKey(object primaryKey) {...}

    public void DeleteByPrimaryKey(object primaryKey) {...}

    public List<T> GetByField(string fieldName, object value) {...}

    public void Insert(T dto) {...}

    public void Update(T dto) {...}
}

然后,我为特定的表/DTO 对它进行了子类化,并为 DB 表布局添加了属性:
[DBTable("note", "note_id", NpgsqlTypes.NpgsqlDbType.Integer)]
[DbField("note_id", NpgsqlTypes.NpgsqlDbType.Integer, "NoteId")]
[DbField("client_id", NpgsqlTypes.NpgsqlDbType.Integer, "ClientId")]
[DbField("title", NpgsqlTypes.NpgsqlDbType.Text, "Title", "")]
[DbField("body", NpgsqlTypes.NpgsqlDbType.Text, "Body", "")]
[DbField("date_added", NpgsqlTypes.NpgsqlDbType.Date, "DateAdded")]
class NoteDAO : DAOBase<NoteDTO>
{
}

感谢 .Net 反射系统,我能够实现大量代码重用和轻松创建新的 ORM。

在 Qt 中做这类事情的最简单方法似乎是使用 QtSql 模块中的模型类。不幸的是,就我而言,它们提供的接口(interface)过于抽象。我至少需要对 QSqlTableModel 不提供的单个提交的事务支持和控制。

你能给我一些关于使用 Qt 解决这个问题的提示,或者给我一些引用资料吗?

更新:

根据 Harald 的线索,我实现了一个与上面的 .Net 类非常相似的解决方案。现在我有两个类。

继承 QObject 并使用元类型系统处理 QObject DTO 的 UniversalDAO:
class UniversalDAO : public QObject
{
    Q_OBJECT

public:
    UniversalDAO(QSqlDatabase dataBase, QObject *parent = 0);
    virtual ~UniversalDAO();

    void insert(const QObject &dto);
    void update(const QObject &dto);
    void remove(const QObject &dto);
    void getByPrimaryKey(QObject &dto, const QVariant &key);
};

还有一个通用的 SpecializedDAO,它将从 UniversalDAO 获得的数据转换为适当的类型:
template<class DTO>
class SpecializedDAO
{
public:
    SpecializedDAO(UniversalDAO *universalDao)
    virtual ~SpecializedDAO() {}

    DTO defaultDto() const { return DTO; }

    void insert(DTO dto) { dao->insert(dto); }
    void update(DTO dto) { dao->update(dto); }
    void remove(DTO dto) { dao->remove(dto); }
    DTO getByPrimaryKey(const QVariant &key);
};

使用上述内容,我将具体的 DAO 类声明如下:
class ClientDAO : public QObject, public SpecializedDAO<ClientDTO>
{
    Q_OBJECT

public:
    ClientDAO(UniversalDAO *dao, QObject *parent = 0) :
        QObject(parent), SpecializedDAO<ClientDTO>(dao)
    {}
};

在 ClientDAO 中,我必须为 UniversalDAO 设置一些数据库信息。这就是我的实现变得丑陋的地方,因为我这样做:
QMap<QString, QString> fieldMapper;
fieldMapper["client_id"] = "clientId";
fieldMapper["name"] = "firstName";

/* ...all column <-> field pairs in here... */

dao->setFieldMapper(fieldMapper);
dao->setTable("client");
dao->setPrimaryKey("client_id");

我在构造函数中执行此操作,因此对于浏览标题的人来说,乍一看它是不可见的。在 .Net 版本中很容易发现和理解。

你有什么想法可以让我做得更好吗?

最佳答案

据我所知,没有任何现成的东西可以直接在 qt 中提供给这个设施。有一些可能的方法。

  • 将字段实现为 Q_PROPERTY,然后通过 Metaclass 系统反射(reflect)并可用于实现通用 DAO 功能
  • 您仍然可以使用 QSqlTableModel 但将写入与事务封装在一起,如果事务失败,请从数据库中刷新模型。可行性取决于您在模型中保存的数据的大小。

  • 我们目前使用基于 TableModel/QSqlRecord 的方法进行读写,我们的系统中没有完成 ORM 映射。我一直在尝试设计一种更通用的方法,但目前我们必须做的重构工作代价高昂。

    这个链接http://giorgiosironi.blogspot.com/2009/08/10-orm-patterns-components-of-object.html与 Qt 无关,但很好地概述了实现模式

    关于sql - Qt 中的持久化类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1468309/

    相关文章:

    python - 使用 Django ORM 加入同一张表

    python - 如何在模型级别分页数据(django)

    mysql - 映射(连接)创建表不允许外键?

    c++ - Qt: c++: 如何使用 QStringList 填充 QComboBox

    xml - 解析 XML 文件时显示部分内容

    c++ - C++ 中的 MongoDB $group 命令

    sql - Postgresql:如何对列中字符的ASCII码求和?

    mysql - 如何优化这个 MySQL 查询? (交叉连接、子查询)

    mysql - SQL 中的条件更新

    java - 与 JPA OneToMany 映射的只读关联