關於qt QSqlDatabase


關於qt中QSqlDatabase使用:如果使用單一的數據庫,以sqlite為例:

QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");

QString dbFileName = "xxx.db";

db.setDatabaseName(dbFileName );

if (db.isOpen()) {

db.open();

}

... //db operator

 

但是當一個程序中需要使用兩個數據庫(比如軟件更新時拷貝原先數據庫中的內容等),則需要操作兩個數據庫,如果只是相似地使用:

 

QSqlDatabase db1 = QSqlDatabase::addDatabase("QSQLITE");

QString dbFileName1 = "xxx.db";

db1.setDatabaseName(dbFileName1);

if (db1.isOpen()) {

db1.open();

}

... //db operator

此時往往會出現以下警告,導致數據庫執行失敗:

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

QSqlDatabasePrivate::addDatabase: duplicate connection name 'qt_sql_default_connection', old connection removed.

   閱讀qt源代碼可以了解到:

static QSqlDatabase addDatabase(const QString& type,
                                 const QString& connectionName = QLatin1String(defaultConnection))

其中關於defaultConnection: QT_STATIC_CONST_IMPL
char *QSqlDatabase::defaultConnection = "qt_sql_default_connection";

 

QSqlDatabase QSqlDatabase::addDatabase(QSqlDriver* driver, const QString&
connectionName)
{
    QSqlDatabase db(driver);
    QSqlDatabasePrivate::addDatabase(db, connectionName);
    return db;
}

 

void QSqlDatabasePrivate::addDatabase(const QSqlDatabase &db, const QString &name)
{
    QConnectionDict *dict = dbDict();
    Q_ASSERT(dict);
    QWriteLocker locker(&dict->lock);

    if (dict->contains(name)) {
        invalidateDb(dict->take(name), name);
        qWarning("QSqlDatabasePrivate::addDatabase: duplicate connection name '%s', old "
                 "connection removed.", name.toLocal8Bit().data());
    }
    dict->insert(name, db);
    db.d->connName = name;
}

觀察QSqlDatabase::addDatabase中還有一個默認參數,其實這才是數據庫真實的名字,而setDatabaseName只是設置數據庫的路徑(別被表面意思忽悠了);從代碼中可以看到addDatabase最終調用其私有對象的addDatabase,最終將數據庫的名字insert到了QConnectionDict。

以下,看到QConnectionDict,大家一定就會恍然大悟,其實,這就是一個HASH Table,形成一個數據庫名字與內容的映射,最終在調用調用

QSqlDatabase QSqlDatabasePrivate::database(const QString& name, bool open)時將用到這個表。

 

class QConnectionDict: public QHash<QString, QSqlDatabase>
{
public:
    inline bool contains_ts(const QString &key)
    {
        QReadLocker locker(&lock);
        return contains(key);
    }
    inline QStringList keys_ts() const
    {
        QReadLocker locker(&lock);
        return keys();
    }

    mutable QReadWriteLock lock;
};

 

   看到這里大家應該能看出以上報錯的原因了吧:由於addDatabase(),默認打開數據庫並設置數據庫名字為qt_sql_default_connection,所以當兩次調用addDatabase(),將會提醒你qt_sql_default_connection已經打開,將關閉原先的數據庫,重新建一個qt_sql_default_connection。

 

   還有一點就是QSqlDatabasePrivate::open()函數調用,

 
 Returns true if the database connection is currently open; otherwise returns false.

   之前想當然的以為文件不存在也會報出錯,但后來實踐證明,open()函數和c中打開文件一樣,如果文件不存在將會建立一個該文件,而不會報錯。

https://www.xuebuyuan.com/3227745.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM