QSqlDatabase&;的正确方法是什么;QSqlQuery?

QSqlDatabase&;的正确方法是什么;QSqlQuery?,database,qt,qt4,qtsql,Database,Qt,Qt4,Qtsql,我对手册感到困惑,我是否应该这样工作: { QSqlDatabase db = QSqlDatabase::addDatabase (...); QSqlQuery query (db); query.exec (...); } QSqlDatabase::removeDatabase (...); 正如文档所指出的,query或db将自动解构。 但这有效率吗 如果我在类中缓存db,如下所示: class Dummy { Dummy() { db = QSqlDataba

我对手册感到困惑,我是否应该这样工作:

{
 QSqlDatabase db = QSqlDatabase::addDatabase (...);
 QSqlQuery query (db);
 query.exec (...);
}

QSqlDatabase::removeDatabase (...);
正如文档所指出的,
query
db
将自动解构。 但这有效率吗

如果我在类中缓存
db
,如下所示:

class Dummy {
  Dummy() { 
    db = QSqlDatabase::addDatabase (...);
  }
  ~Dummy() {
    db.close();
  }

  bool run() {
    QSqlQuery query (db);
    bool retval = query.exec (...);
    blabla ...
  }

  private:
    QSqlDatabase db;
};
有时我会看到如下警告:

QSqlDatabasePrivate::removeDatabase: connection 'BLABLA' is still in use, all queries will cease to work.

即使我没有调用
run()

QSqlDatabase和QSqlQuery都是围绕具体实现的轻量级包装,所以您的第一个示例也很好。如果在添加连接时提供名称,或使用默认数据库,则只需编写“QSqlDatabase db(name)”即可使数据库对象的开销非常小


removeDatabase相当于关闭文件(对于sqlite)或连接(对于ODBC/MySql/Postgres),因此这通常是程序终止时要做的事情。正如警告所说,您必须确保引用该数据库的所有数据库和查询对象都已被销毁,否则可能会发生不好的事情。

使用
addDatabase
创建
QSqlDatabase
对象或调用
removeDatabase
时,您只是在关联或解除元组关联(驱动程序、主机名:端口、数据库名称、用户名/密码)设置为名称(如果未指定连接名称,则设置为默认连接名称)。
SQL驱动程序已实例化,但只有在调用
QSqlDatabase::open
时才会打开数据库

该连接名称是在应用程序范围内定义的。因此,如果在使用该名称的每个对象中调用
addDatabase
,则会更改使用相同连接名称的所有
QSqlDatabase
对象,并使其上所有活动的查询无效

您引用的第一个代码示例演示了如何通过确保:

  • 在通过调用
    QSqlQuery::finish()
    关闭数据库之前,所有
    QSqlQuery
    都会从
    QSqlDatabase
    中分离,当
    QSqlQuery
    对象超出范围时,这是自动的
  • 调用
    QSqlDatabase::removeDatabase
    时,具有相同连接名称的所有
    QSqlDatabase
    都是
    close()
    d(当
    QSqlDatabase
    对象超出范围时,也会自动调用
    close()
创建QSqlDatabase时,根据希望连接在应用程序生命周期(1)内保持打开状态还是仅在需要时保持打开状态(2),您可以:

  • 将单个
    QSqlDatabase
    实例保存在单个类中(例如,在主窗口中),并通过直接传递
    QSQLDABASE
    或仅传递给
    QSQLDABASE::database
    以获取
    QSQLDABASE
    实例的连接名称,在需要它的其他对象中使用它。
    QSQLDABASE::database
    使用
    QHash
    从其名称检索
    QSQLDABASE
    ,因此,它可能比在对象和函数之间直接传递
    QSqlDatabase
    对象慢得多,而且如果使用默认连接,甚至不需要在任何地方传递任何内容,只需调用
    QSqlDatabase::database()
    ,而不需要任何参数

    // In an object that has the same lifetime as your application
    // (or as a global variable, since it has almost the same goal here)
    QSqlDatabase db;
    
    // In the constructor or initialization function of that object       
    db = QSqlDatabase::addDatabase("QSQLDRIVER", "connection-name"); 
    db.setHostname(...);
    // ...
    if(!this->db.open())  // open it and keep it opened
    {
        // Error handling...
    }
    
    // --------
    // Anywhere you need it, you can use the "global" db object 
    // or get the database connection from the connection name        
    QSqlDatabase db = QSqlDatabase::database("connection-name"); 
    QSqlQuery query(db);             
    
  • 配置
    QSQLDABASE
    一次,打开它以测试参数是否正确,然后丢弃实例。连接名称仍然可以在任何地方访问,但必须重新打开数据库:

    {
        // Allocated on the stack
        QSqlDatabase db = QSqlDatabase::addDatabase("QSQLDRIVER", "connection-name"); 
        db.setHostname(...);
        // ...
        if(!this->db.open()) // test the connection
        {
           // Error handling
        }
    // db is closed when it goes out of scope
    } 
    
    {
        // Same thing as for (1), but by default database() opens 
        // the connection if it isn't already opened 
        QSqlDatabase db = QSqlDatabase::database("connection-name"); 
        QSqlQuery query(db);
    
    // if there is no other connection open with that connection name,
    // the connection is closed when db goes out of scope
    } 
    
    在这种情况下,请注意不应显式关闭数据库,因为可以以可重入方式使用同一数据库连接的多个对象(例如,如果函数a使用连接并调用B,B也使用连接。如果B在将控制权返回给a之前关闭连接,则a的连接也将关闭,这可能是一件坏事)


  • 我发现指令必须严格按照下面的顺序运行,否则数据库连接或查询会出现问题。这在Qt5中有效

    QSqlQueryModel *model = new QSqlQueryModel;
    db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(fileName);
    
    if (db.isValid())
    {
        db.open();
        if (db.isOpen())
        {
            QSqlQuery searchQuery(db);
            searchQuery.prepare("SELECT * FROM myTable");
            searchQuery.exec();
            if(searchQuery.isActive())
            {
                model->setQuery(searchQuery);
                sui->DBDisplay->setModel(model);
                db.close();
            } else {
                qDebug() << "query is not active";
            }
        } else {
            qDebug() << "DB is not open";
        }
    } else {
        qDebug() << "DB is not valid";
    }
    
    QSqlQueryModel*model=新的QSqlQueryModel;
    db=QSqlDatabase::addDatabase(“QSQLITE”);
    db.setDatabaseName(文件名);
    if(db.isValid())
    {
    db.open();
    if(db.isOpen())
    {
    QSqlQuery搜索查询(db);
    searchQuery.prepare(“从myTable中选择*);
    searchQuery.exec();
    if(searchQuery.isActive())
    {
    模型->设置查询(搜索查询);
    sui->DBDisplay->setModel(model);
    db.close();
    }否则{
    
    qDebug()我遇到了这个问题,在进行此调整后,我能够关闭调用
    QSqlDatabase::removeDatabase(QSqlDatabase::database(“database NAME”);