详细描述
QSqlDatabase 类代表一个数据库连接(LZ 觉得这个类叫做 QSqlDatabaseConnection 意思更明确)。
QSqlDatabase 类提供一个通过连接去访问数据库的接口。一个 QSqlDatabase 实例代表一个连接。该连接提供了通过Qt 支持的数据库驱动 去访问数据库的接口,这些驱动派生自 QSqlDriver 类。或者,你可以从 QSqlDriver 类子类化你自己的数据库驱动。
通过调用 QSqlDatabase 的静态函数 addDatabase() 去创建一个数据库连接(也就是一个QSqlDatabase实例), 你可以指定你要使用的数据库驱动或者数据库驱动的类型(也就是你将要访问什么类型的数据库?)和一个连接名。一个连接是通过自己的名字被识别的,而不是通过连接到的数据库的名字。你可以拥有(创建)多个连接到一个数据库,也就是一个数据库可以拥有多个连接。QSqlDatabase 同时也支持默认连接,也就是无名(未命名)的连接。要创建默认连接,在你调用 addDatabase() 函数时不要传连接名。随后,当你调用任何带有连接名参数的静态成员函数时如果你不传连接名参数,那么久假定默认连接名作为连接参数(你可以不穿参数然后打印默认的连接其实就是“qt_sql_default_connection”)。以下的代码片段显示怎么创建和打开一个到PostgreSQL 数据库的默认连接:
QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL");
db.setHostName("acidalia");
db.setDatabaseName("customdb");
db.setUserName("mojito");
db.setPassword("J0a1m8");
bool ok = db.open();
一旦 创建了 QSqlDatabase 对象,通过 setDatabaseName(), setUserName(), setPassword(), setHostName(), setPort(), and setConnectOptions(). 去设置连接参数。然后调用open() 去激活到数据库的物理连接。该连接是不可用的直到你打开它。
上面定义的连接会是默认连接,因为我们没有传一个连接名给addDatabase()。随后,你可以通过调用没有连接名参数的database() 得到默认连接:
QSqlDatabase db = QSqlDatabase::database();
QSqlDatabase 是一个值类(value class)。通过一个QSqlDatabase 实例去改变一个数据库连接将会影响另外一个代表同样连接的QSqlDatabase实例。可以使用 cloneDatabase()去创建一个基于已经存在的数据库连接。
如果你创建多个数据库连接,在你调用 addDatabase()时给每个数据库连接指定一个唯一的连接名。使用 带连接名参数的database()函数去得到那个连接。使用带连接名的 removeDatabase() 函数去移除一个数据库连接。如果你尝试要移除一个被其它QSqlDatabase对象引用的数据库连接 QSqlDatabase 会输出警告信息。使用 contains() 函数去查看给定的连接名是否在连接链表中。
一旦连接建立,你可以调用 tables() 去得到数据库中的表名链表,调用 primaryIndex()去得到指定表(通过参数指定)的主键, 调用record() 可以得到表或视图中关于表的字段的元信息(比如:字段名)。
注意:不赞成使用 QSqlDatabase::exec() ,使用 QSqlQuery::exec()替代它。
如果你的数据库驱动支持事务,使用transaction()去开启一个事务,然后使用commit() 或者 rollback() 去完成这个事务。可以使用 hasFeature() 去访问数据库驱动是否支持事务等其他数据库特性。
注意:当使用事务transaction()时,你必须在你创建你的query之前开始事务。(这里的query LZ 觉得不是指QSqlQuery对象而是指的是SQL query,也就是执行SQL的数据库操作,如,exec(SQL)。因为我在工程中有些地方是在事务开启之前创建QSqlQuery对象,有些地方是在事务开启之后创建QSqlQuery对象的,但是都是不影响事务的正常提交的,而要执行的SQL语句很明显是要放在事务开始之后,这里也是楼主自己的工作经验所得,楼主用的是SQLite数据库,对于其他的数据库就不知道是不是也是这种情况。如果怕出错最好把创建的QSqlQuery对象创建也放在事务开启之后,这样就万无一失了)。
如果有错误发生, lastError()会返回错误相关的信息。
通过 drivers()得到可访问的SQL驱动的的名字。通过isDriverAvailable()检验特定驱动是否可访问。如果你创建你自定义的驱动,你必须通过 registerSqlDriver()去注册它。几个重要的API介绍
QSqlDatabase QSqlDatabase::addDatabase(const QString &type, const QString &connectionName = QLatin1String( defaultConnection ))
增加一个使用类型驱动为type和连接名为connectionName的接数据库连接到数据库连接链表中。如果已经存在一个叫connectionName的数据库连接,那么这个连接(已存在的数据库连接)就会被移除。
数据库连接是通过connectionName去引用的,改函数返回新加入的数据库连接。
如果驱动类型type不可访问或者加载, isValid() 返回false。
如果没有指定connectionName,新的数据库连接就是默认的连接,随后调用 不带连接名参数的database()将会返回默认连接(QSqlDatabase )。如果
提供了connectionName,使用database(connectionName) 去得到该数据库连接(QSqlDatabase )。
警告:如果你添加与现有连接名字相同的连接,新的连接会代替老的连接。如果你多次调用这个没有指定特定连接名connectionName的函数,默认连接将是替换的那一个。
在你使用数据库连接之前,必须先初始化。例如,调setDatabaseName(),setUserName(),setPassword(),setHostName(),setPort(),setConnectOptions() ,最后open().
注意:这个函数是线程安全的。
void QSqlDatabase::removeDatabase(const QString &connectionName)
从数据库连接链表中移除名为connectionName的那个数据库连接。
警告:当调用这个函数时必须确保没有打开的查询(queries),否则会发生资源泄露。
例子:
// WRONG
QSqlDatabase db = QSqlDatabase::database("sales");
QSqlQuery query("SELECT NAME, DOB FROM EMPLOYEES", db);
QSqlDatabase::removeDatabase("sales"); // will output a warning
// "db" is now a dangling invalid database connection,(db此时已经无效)
// "query" contains an invalid result set(query包含了无效的结果集)
正确的用法:
{
QSqlDatabase db = QSqlDatabase::database("sales");
QSqlQuery query("SELECT NAME, DOB FROM EMPLOYEES", db);
}
// Both "db" and "query" are destroyed because they are out of scope
//数据库连接db和查询query都出了作用域这个时候再去从数据库连接名链表中删除这个数据库连接对应的连接名就不会出现资源泄露和不可用的现象
QSqlDatabase::removeDatabase("sales"); // correct
要删除默认连接,就是已经通过 调用没有指定连接名addDatabase()创建的数据库默认连接。你可以在database()返回的数据库连接调用 connectionName() 去获得默认的数据库连接名。注意,如果,默认的连接没有被创建,则调用 database()返回的是一个无效的数据库(连接)。
removeDatabase(const QString &connectionName)同样也是线程安全的。