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

  • 相关阅读:
    学习进度笔记16
    《软件架构师的12项修炼》阅读笔记1
    学习进度笔记15
    CSS前端性能优化
    多行文本溢出,显示省略号
    VIM编辑器使用
    iOS 兼容性处理
    javascript 对象
    JS滚轮事件(mousewheel/DOMMouseScroll)了解
    MarkDown编辑器基础使用教程
  • 原文地址:https://www.cnblogs.com/sggggr/p/13569902.html
Copyright © 2020-2023  润新知