2011-10-06 191 views
26

我得到了與手動迷茫,我應該像這樣工作:QSqlDatabase&QSqlQuery的正確方法是什麼?

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

QSqlDatabase::removeDatabase (...); 

正如文件指出,querydb將自動解構。 但是這是有效的?

嗯,如果我緩存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()

回答

41

當你創建一個QSqlDatabase物體addDatabase或當你調用removeDatabase,你只是關聯或取消關聯的元組(驅動程序,主機名:端口,數據庫名稱,用戶名/密碼)的名稱(或默認連接名稱,如果你沒有指定連接名稱)。
SQL驅動程序已實例化,但數據庫僅在您致電QSqlDatabase::open時纔會打開。

該連接名稱在整個應用程序範圍內定義。因此,如果在每個使用該對象的對象中調用addDatabase,那麼您將更改所有使用相同連接名稱的QSqlDatabase對象,並使所有在其上激活的查詢無效。

第一個代碼示例,你列舉說明了如何正確地撇清連接名稱,通過確保:通過調用QSqlQuery::finish(),這是自動關閉數據庫之前

  • 所有QSqlQueryQSqlDatabase分離時的QSqlQuery對象超出範圍,
  • 所有QSqlDatabase具有相同的連接名稱是close() d,當你調用QSqlDatabase::removeDatabaseclose()也被自動調用時QSqlDatabase對象超出SC的OPE)。

當您創建QSqlDatabase,這取決於你是否希望連接保持打開的應用程序生命週期(1)或僅在需要時(2),您可以:

  1. 保持單在一個單獨的類QSqlDatabase實例(例如,在你的主窗口),並用它在其他對象直接傳遞QSqlDatabase或只是傳遞給QSqlDatabase::database得到QSqlDatabase實例背面的連接名稱需要它的。 QSqlDatabase::database使用QHash檢索從它的名字QSqlDatabase,所以它可能是可以忽略不計不是直接傳遞對象和功能之間的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);    
    
  2. 配置QSqlDatabase一次,打開它來測試的參數是正確的,並且溝實例。連接名稱,仍然可以訪問任何地方,但該數據庫將不得不重新打開:

    { 
        // 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關閉控制返回給A之前的連接,該連接也將被關閉了,這可能是一個壞事)。

+0

我是有這個問題,使這種適應我能夠關閉數據庫調用''QSqlDatabase :: removeDatabase(QSqlDatabase ::數據庫(「數據庫名」)之後;'' –

3

QSqlDatabase和QSqlQuery是具體實現的輕量級包裝,所以你的第一個例子很好。如果您在添加連接時提供了一個名稱,或者使用了默認數據庫,那麼只需編寫'QSqlDatabase db(name)'即可爲您提供幾乎沒有開銷的數據庫對象。

removeDatabase相當於關閉文件(對於sqlite)或連接(對於ODBC/MySql/Postgres),所以這通常是您在程序終止時要做的事情。正如警告所說,您必須確保引用該數據庫的所有數據庫和查詢對象已被銷燬,否則可能發生不良事情。

0

我發現,說明必須在其低於要不然你有問題,無論是與數據庫連接或查詢的順序正好運行。這在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"; 
} 
相關問題