Qt 數(shù)據(jù)庫QSqlDatabase使用示例
記錄一些在QT中使用QSqlDatabase操作數(shù)據(jù)庫時,需要注意的地方
創(chuàng)建數(shù)據(jù)庫
bool CDBOperatorAbstract::_openDBConn(CDatabaseConfig config) { QWriteLocker locker(&m_locker); QSqlDatabase db; if(QSqlDatabase::contains(m_connectionName)) { db = QSqlDatabase::database(m_connectionName); QStringList tables = db.tables(); if(db.isOpen() && tables.contains(config.m_databaseName)) { m_isConnected = true; return true; } } else { // 此時目標(biāo)數(shù)據(jù)庫不一定存在,不指定數(shù)據(jù)庫名,會默認(rèn)連接到mysql的主數(shù)據(jù)庫(mysql數(shù)據(jù)庫) db = QSqlDatabase::addDatabase("QMYSQL",m_connectionName); db.setHostName(config.m_hostAddress); // 數(shù)據(jù)庫服務(wù)器IP db.setPort(config.m_port); // 端口號 db.setUserName(config.m_userName); // 用戶名 db.setPassword(config.m_userPwd); // 密碼 } // 連接數(shù)據(jù)庫 if(!db.open()) { qDebug() << db.lastError().text(); m_isConnected = false; return false; } QSqlQuery query(db); QString strSql = QString("CREATE DATABASE IF NOT EXISTS `%1`").arg(config.m_databaseName); //執(zhí)行建表語句,若執(zhí)行成功 if(query.exec(strSql)) { //若查詢語句有錯 if(query.lastError().isValid()) { qDebug()<< query.lastError().text(); m_isConnected = false; return false; } } else { m_isConnected = false; return false; } // 確認(rèn)目標(biāo)數(shù)據(jù)庫創(chuàng)建成功,關(guān)閉之前打開的默認(rèn)數(shù)據(jù)庫 db.close(); // 重新設(shè)置連接的數(shù)據(jù)庫名 db.setDatabaseName(config.m_databaseName); // 重新打開數(shù)據(jù)庫 if(!db.open()) { m_isConnected = false; return false; } else { m_isConnected = true; return true; } }
在上述創(chuàng)建數(shù)據(jù)庫的代碼中有幾個需要注意的地方:
1、一個QSqlDatabase對象表示的是一個數(shù)據(jù)庫連接,而不是字面上的數(shù)據(jù)庫(數(shù)據(jù)庫連接與數(shù)據(jù)庫的關(guān)系是:一個數(shù)據(jù)庫連接可以通過修改配置連接到多個數(shù)據(jù)庫,一個數(shù)據(jù)庫也可以有多個數(shù)據(jù)庫連接)
2、addDatabase()方法需要指定數(shù)據(jù)庫驅(qū)動類型,如MySQL、SQLite……,如果沒有指定連接名,將默認(rèn)使用defaultConnection作為連接名。對于同一個連接,重復(fù)調(diào)用addDatabase(),會提示:
QSqlDatabasePrivate::addDatabase: duplicate connection name
‘qt_sql_default_connection’, old connection removed.
3、removeDatabase()刪除數(shù)據(jù)庫連接,需要在確保所有QSqlQuery查詢操作執(zhí)行完畢并且銷毀,否則會提示:
QSqlDatabasePrivate::removeDatabase: connection ‘qt_sql_default_connection’ is still in use, all queries will cease to work.
4、在進(jìn)行數(shù)據(jù)庫連接時,目標(biāo)數(shù)據(jù)庫可能還不存在,這時候可以不指定數(shù)據(jù)庫名進(jìn)行連接,此會將連接到數(shù)據(jù)庫服務(wù)器的主數(shù)據(jù)庫,例如我使用的是MySQL數(shù)據(jù)庫服務(wù)器,就會連接到mysql數(shù)據(jù)庫
5、數(shù)據(jù)庫連接建立成功后,創(chuàng)建目標(biāo)數(shù)據(jù)庫(不存在時才創(chuàng)建),確保目標(biāo)數(shù)據(jù)庫創(chuàng)建成功后,先關(guān)閉之前的數(shù)據(jù)庫連接,設(shè)置數(shù)據(jù)庫名稱后再重新打開。(只有重新打開數(shù)據(jù)庫連接,數(shù)據(jù)庫配置才會生效)
多線程使用數(shù)據(jù)庫
QSqlDatabase是非線程安全的,意味著在多線程環(huán)境下同時使用同一個數(shù)據(jù)庫連接對象可能會導(dǎo)致競態(tài)條件和數(shù)據(jù)一致性問題。因此,每個線程最好都維護(hù)一個獨(dú)立的數(shù)據(jù)庫連接,并且在同一個線程中創(chuàng)建、使用和關(guān)閉數(shù)據(jù)庫連接。如果數(shù)據(jù)庫連接有父對象,它和父對象也必須在同一個線程。
一般用QMap來管理線程和對應(yīng)的數(shù)據(jù)庫連接,可以用QMap<QThread*,QSqlDatabase*>來存儲,也可以用QMap<QThread*,QString>來存儲(存連接名)
由于程序可能在各個地方操作數(shù)據(jù)庫,為了讓數(shù)據(jù)庫連接的創(chuàng)建和使用保持在同一個線程中,可以用QMetaObject::invokeMethod()將數(shù)據(jù)庫的創(chuàng)建、使用、關(guān)閉都移動到數(shù)據(jù)庫連接所在的線程中
bool CDBOperatorAbstract::checkIsInWorkThread() { if(QThread::currentThread() == this->m_pThread) return true; else return false; } bool CDBOperatorAbstract::openDBConn(CDatabaseConfig config) { if(checkIsInWorkThread()) { return _openDBConn(config); } else { bool isOk = false; QMetaObject::invokeMethod(this,"_openDBConn",Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool,isOk), Q_ARG(CDatabaseConfig,config)); return isOk; } }
用BlockingQueuedConnection的連接方式,會將目標(biāo)函數(shù)放在接收者的生存線程中執(zhí)行,并且阻塞發(fā)送者所在的線程,直到目標(biāo)函數(shù)執(zhí)行完畢。
增刪改查
numRowsAffected()這個函數(shù)返回最后一個執(zhí)行的 SQL 查詢語句所影響的行數(shù)。通常用于 INSERT、UPDATE 或 DELETE 查詢之后,用來確定有多少行受到了影響。返回值是一個整數(shù)。
lastInsertId()這個函數(shù)用于在主鍵自增的情況下,獲取最后一次 INSERT 操作生成的主鍵,返回值為QVariant類型,需要根據(jù)主鍵實(shí)際的類型進(jìn)行轉(zhuǎn)換。
size()這個函數(shù)用于獲取當(dāng)前查詢結(jié)果集中的記錄數(shù)。例如執(zhí)行 SELECT 查詢后需要確定返回的記錄數(shù)量。返回值是一個整數(shù)。
isValid()這個函數(shù)用于檢查 QSqlQuery 對象是否有效,即它是否正常地初始化以執(zhí)行 SQL 查詢。
到此這篇關(guān)于Qt 數(shù)據(jù)庫QSqlDatabase使用示例的文章就介紹到這了,更多相關(guān)Qt QSqlDatabase內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言中auto,register,static,const,volatile的區(qū)別詳細(xì)解析
以下是對C語言中auto,register,static,const,volatile的區(qū)別進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過來參考下2013-09-09QT實(shí)現(xiàn)自定義Http客戶端的示例代碼
這篇文章主要為大家詳細(xì)介紹了QT如何實(shí)現(xiàn)自定義Http客戶端的,可以實(shí)現(xiàn)支持get,post請求方式;支持連接超時處理;支持網(wǎng)絡(luò)錯誤,嘗試重連等功能,感興趣的小伙伴可以學(xué)習(xí)一下2022-11-11一文詳解matlab實(shí)現(xiàn)形態(tài)學(xué)圖像處理
這篇文章主要為大家介紹了matlab實(shí)現(xiàn)形態(tài)學(xué)圖像處理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03