C++ 从QThread返回QSqlQuery结果

C++ 从QThread返回QSqlQuery结果,c++,mysql,multithreading,qt,C++,Mysql,Multithreading,Qt,我正在使用Qt5.3.1SQL模块访问MySQL 5.6数据库。目前,我尝试将部分代码从主线程移动到自定义线程,以允许GUI线程在DB更新期间保持响应 我知道一切(包括建立连接)都必须移动到自定义线程。我使用排队信号和插槽来实现这一点,它工作正常 然而,有一件事我不确定:如何将查询结果返回到主线程?当然我会用一个信号。但我应该在那个信号中返回什么样的对象呢 我应该返回QSqlQuery吗?我认为这将是危险的,因为QSqlQuery以某种方式连接到连接/数据库 我是否应该使用record()返回从

我正在使用Qt5.3.1SQL模块访问MySQL 5.6数据库。目前,我尝试将部分代码从主线程移动到自定义线程,以允许GUI线程在DB更新期间保持响应

我知道一切(包括建立连接)都必须移动到自定义线程。我使用排队信号和插槽来实现这一点,它工作正常

然而,有一件事我不确定:如何将查询结果返回到主线程?当然我会用一个信号。但我应该在那个信号中返回什么样的对象呢

我应该返回QSqlQuery吗?我认为这将是危险的,因为QSqlQuery以某种方式连接到连接/数据库

我是否应该使用record()返回从查询中获取的QSqlRecord对象列表?不幸的是,如果这是安全的,文档中一句话也没有说


安全返回结果的正确容器/方法是什么?

例如,如果数据库包含个人详细信息,您可以创建一个单独的类,从QObject派生:-

class Person : public QObject
{
    Q_OBJECT

    public:
        Person();

    private:
        QString m_firstName;
        QString m_surname;
        QString m_address
        QDateTime m_dateOfBirth;
};
然后,为了使用信号和插槽,检索数据库记录,填充Person对象并发送信号和插槽。然后,您创建的类可以表示数据库中的表

但是,一种更简单的方法是使用QMap并用它发出信号:-

QMap personMap;
personMap["name"] = sqlRecord.value().toString("name");
personMap["surname"] = sqlRecord.value().toString("surname");
personMap["address"] = sqlRecord.value().toString("address");
...etc
发出一个接受令牌和映射的函数可能是一个好主意,其中令牌表示映射包含的信息类型:-

emit RetrievedData("Person", personMap);
我将避免发送SqlRecord或与存储数据的底层方法有关的任何内容。它总是好用的。这样,您就可以决定用另一种机制替换数据库存储,而不必重构所有其他代码

-----------回应评论------------

使用sql记录填充映射。为简单起见,我们假设所有返回的项都是字符串。 如果记录项是数字,只需在存储到地图之前转换为字符串即可

QMap PopulateMap(SQLRecord& sqlRecord)
{
    QMap map;

    for(int i=0; i<sqlRecord.count(); ++i)
    {
        map[sqlRecord.fieldName(i)] = sqlRecord.value(i).toString();
    }

    return map;
}
QMap PopulateMap(SQLRecord&SQLRecord)
{
QMap地图;

对于(int i=0;iHi!在我看来,从面向对象的角度讲,如果你有一个线程来管理与数据库的每一次交互,那么你应该在这部分代码中保留所有sql对象。对于数据库,你提取一些数据,那么为什么不传输这些数据抛出信号/插槽呢?我不知道我是否必须在这里谈论指针/引用或值。我想创建一个通用的QThread派生的查询线程类,该类应该能够返回通用结果,独立于实际使用的SQL语句。我明白你的意思。但这样,我需要为每个语句实现一个新的SQL线程类(即使只有很少的差异)。我希望我能创建一个通用的、可重用的类。@Silicomancer,对不起,我不明白你的意思。你有一个单独的线程执行SQL查询。当它收到结果时,它会发出一个信号,其中的数据可以包装在一个类中,也可以存储在一个QMap中。为什么你需要多个SQL线程类,或者你创建了多个SQL线程类从QThread继承的查询类?关于您的“class Person”建议:不同的语句返回不同的数据。我需要为每个SQL语句提供特定的信号(以及特定的类)。关于您的“QMap personMap”建议:信号始终是相同的,但我仍然需要一个特定的类,可以为每个语句执行记录到映射的转换。为什么需要一个特定的类?您可以创建一个函数,从SQLRecord中检索计数,然后通过它们进行迭代,按索引获取每个字段名和适当的值和st在映射中对它们进行排序-查看编辑后的答案。那么线程如何知道转换函数?提供函数指针或函子?我可能可以这样做。目前我正在考虑第三种方法。我可以编写一个通用线程类,但提供一个使用您想法的特定工作线程。这还允许可选的同步使用无线程的辅助进程进行nous访问。