关于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

原文地址:https://www.cnblogs.com/sggggr/p/13569902.html