運作環境:
windows10
QT5.1.1 mingw 32bit
Mysql5.7
問題描述:
使用全局QSqlDatabase對象,在子線程調用主線程建立的資料庫連接配接,與資料建立連接配接的代碼如下:
//連接配接資料庫
void MainWindow::connectMYSQL(QString linkName)
{
if (QSqlDatabase::contains(linkName))//判斷testConnect連接配接是否存在并連接配接
{
database = QSqlDatabase::database(linkName);
}
else //未連接配接則建立資料庫連接配接
{
database=QSqlDatabase::addDatabase("QMYSQL",linkName);//建立資料庫連接配接,并為其命名testConnect
database.setHostName("localhost"); //連接配接資料庫主機名,這裡需要注意(若填的為”10.129.41.30“,出現不能連接配接,則改為localhost)
database.setPort(3307); //連接配接資料庫端口号,與設定一緻
database.setUserName("root"); //資料庫使用者名,與設定一緻
database.setPassword("root"); //資料庫密碼,與設定一緻
}
if(!database.open())
{
qDebug()<<"fail to connect mysql:"<<database.lastError().text();
return;
}
}
運作提示:
QSqlDatabasePrivate::database: requested database does not belong to the calling thread.
fail to connect mysql:"Driver not loaded Driver not loaded"
***database open failed (注:“***database”為實際建立的資料庫名稱)
QSqlQuery::exec: database not open
解決方案:
1、各線程建立各自的連結,使用完畢後自動斷開連結;直接使用以下語句斷開連結:
//斷開與資料庫的連結
void noLink(QString linkName)
{
QSqlDatabase::removeDatabase(linkName);
}
報錯,提示:
QSqlDatabasePrivate::removeDatabase: connection ‘myConnection’ is still in use, all queries will cease to work
2、在網上查了好多資料,大部分都說直接将全局QSqlDatabase對象改為局部變量,但一旦改為局部變量,對于我目前的代碼結構,後期維護肯定會需要耗費更多的成本。最終找到了解決方案,代碼如下:
//斷開與資料庫的連結
void noLink()
{
QString connection;
connection = m_db.connectionName();
m_db.close();
m_db = QSqlDatabase();
m_db.removeDatabase(connection);
}
問題原因:
1、主線程初始化的資料庫隻能在主線程用,子線程初始化的資料庫隻能自子線程用。
2、在斷開與資料庫的連結時,必須釋放該連接配接的所有查詢,即删除所有與該連接配接有關的query;同時在釋放該連接配接時,需要先擷取該連接配接的連接配接名,然後先關閉目前資料庫,并将目前資料庫使用預設構造函數覆寫,最後再移除目前連接配接。
參考資料:
https://blog.csdn.net/daxuezdj7/article/details/89556250
https://blog.csdn.net/owen7500/article/details/53192060