问题:
很多QT新手多线程使用数据库时,经常遇到警告:
QSqlDatabasePrivate::database: requested database does not belong to the calling thread.
究其原因,帮助助手明确说明
A connection can only be used from within the thread that created it. Moving connections between threads or creating queries from a different thread is not supported.
也就是在QT里,数据库的连接对象,只能在本线程中使用,不能跨线程使用。
在多线程中便利使用数据库:
1)实现连接函数,使用线程ID作为连接名
bool MySQL::connectDb(QString& errorMsg)
{
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL", QString::number((quint64)QThread::currentThreadId())); //连接的MYSQL的数据库驱动
db.setHostName("127.0.0.1"); //主机名
db.setPort(3306); //端口
db.setDatabaseName("Test"); //数据库名
db.setUserName("root"); //用户名
db.setPassword("test123456"); //密码
if (!db.open())
{
errorMsg = db.lastError().text();
qDebug() << "open database failed:" << errorMsg;
return false;
}
return true;
}
2)实现断连函数
void MySQL::disconnectDb()
{
QString dbName = QString::number((quint64)QThread::currentThreadId());
{
QSqlDatabase dbConnected = QSqlDatabase::database(dbName);
if (dbConnected.isValid())
{
dbConnected.close();
}
}
QSqlDatabase::removeDatabase(dbName);
}
注意QSqlDatabase::database(dbName);这句要写在大括号里,否则QSqlDatabase::removeDatabase时会报警告:
QSqlDatabasePrivate::removeDatabase: connection '191340' is still in use, all queries will cease to work.
因为调用QSqlDatabase::database(dbName)会使连接的引用计数+1,调用QSqlDatabase::removeDatabase时,连接的引用计数不为1就会报如上警告。
使用示例:
//伪代码
std::thread([](){
MySql db;
//在线程里连接数据库
QString errText;
db.connectDb(errText);
//读写数据库
db.select...
db.insert...
...
//断开数据库
db.disconnectDb();
)