QSqlDatabase 使用小结,解决部分数据库操作导致程序崩溃的办法
2010-08-04 16:18
609 查看
这两天都在为 QSqlDatabase 类头疼 因为涉及多个连接 连接到同一个数据库 而又没有对各个连接设置名称 网上大部分简易教程都是采用默认数据库连接名称 这样就会导致在对其中一个数据库连接进行操作时 影响到其它数据连接的操作(其实本质上他们是同一个连接) 因为我采用多文档窗体在各个窗体处理不同的数据连接 所以移除或者改变一个连接 也会导致其它连接跟着受到影响 直接导致了程序假死崩溃
本来毫无头绪 不知道个所以然 参照前辈的文章来写程序 也没翻看相应的文档解释 导致头大了两天 唉
现在贴出文档的部分信息
以上是addDatabase的说明 第一个是连接数据库的类型 第二个是连接名称 如果我们直接采用
这样的形式进行设置实例的话 那么此时连接的名称是qt的默认数据连接名称 当然这就是导致多个连接实例操作同一个数据库出错的根源所在
所以我们必须采用下面这样的形式进行连接数据库
currentConnName必须与其它实例不相同 不然也会导致多个连接操作出错
警告信息已经说的很清楚
如果使用的连接名称已经存在 则先前那个连接将被替换掉。
再看看removedatabase
这里removedatabase也必须传入相应要移除的连接名称 如果有先前多个连接采用默认的数据连接名称 或者是相同的名称 不管你移除哪个连接(实际上是同一个) 都会导致程序出错
移除前 需要将该连接上取得的数据 资源释放掉 不然将可能导致内存泄漏
非默认连接名称的QSqlDatabase实例 在使用query 或者model进行操作的时候 实例化query或者model都必须设置使用的QSqldatabase 其实就是设置连接名称
形如如下所示
或者
其实也是一知半解 下面贴一下改造过的数据库连接类
h文件
cpp文件
本来毫无头绪 不知道个所以然 参照前辈的文章来写程序 也没翻看相应的文档解释 导致头大了两天 唉
现在贴出文档的部分信息
QSqlDatabase QSqlDatabase::addDatabase ( const QString & type, const QString & connectionName = QLatin1String( defaultConnection ) ) [static] Adds a database to the list of database connections using the driver type and the connection name connectionName. If there already exists a database connection called connectionName, that connection is removed. The database connection is referred to by connectionName. The newly added database connection is returned. If type is not available or could not be loaded, isValid() returns false. If connectionName is not specified, the new connection becomes the default connection for the application, and subsequent calls to database() without the connection name argument will return the default connection. If a connectionName is provided here, use database(connectionName) to retrieve the connection. Warning: If you add a connection with the same name as an existing connection, the new connection replaces the old one. If you call this function more than once without specifying connectionName, the default connection will be the one replaced. Before using the connection, it must be initialized. e.g., call some or all of setDatabaseName(), setUserName(), setPassword(), setHostName(), setPort(), and setConnectOptions(), and, finally, open(). Note: This function is thread-safe. See also database(), removeDatabase(), and Threads and the SQL Module.
以上是addDatabase的说明 第一个是连接数据库的类型 第二个是连接名称 如果我们直接采用
dbconn = QSqlDatabase::addDatabase("QSQLITE); dbconn.setDatabaseName("./DbfInUse/"+SqliteDB::DbName);
这样的形式进行设置实例的话 那么此时连接的名称是qt的默认数据连接名称 当然这就是导致多个连接实例操作同一个数据库出错的根源所在
所以我们必须采用下面这样的形式进行连接数据库
dbconn = QSqlDatabase::addDatabase("QSQLITE",currentConnName); dbconn.setDatabaseName("./DbfInUse/"+SqliteDB::DbName);
currentConnName必须与其它实例不相同 不然也会导致多个连接操作出错
警告信息已经说的很清楚
Warning: If you add a connection with the same name as an existing connection, the new connection replaces the old one. If you call this function more than once without specifying connectionName, the default connection will be the one replaced.
如果使用的连接名称已经存在 则先前那个连接将被替换掉。
再看看removedatabase
void QSqlDatabase::removeDatabase ( const QString & connectionName ) [static] Removes the database connection connectionName from the list of database connections. Warning: There should be no open queries on the database connection when this function is called, otherwise a resource leak will occur. Example: // 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, // "query" contains an invalid result set The correct way to do it: { 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 QSqlDatabase::removeDatabase("sales"); // correct To remove the default connection, which may have been created with a call to addDatabase() not specifying a connection name, you can retrieve the default connection name by calling connectionName() on the database returned by database(). Note that if a default database hasn't been created an invalid database will be returned. Note: This function is thread-safe. See also database(), connectionName(), and Threads and the SQL Module.
这里removedatabase也必须传入相应要移除的连接名称 如果有先前多个连接采用默认的数据连接名称 或者是相同的名称 不管你移除哪个连接(实际上是同一个) 都会导致程序出错
移除前 需要将该连接上取得的数据 资源释放掉 不然将可能导致内存泄漏
非默认连接名称的QSqlDatabase实例 在使用query 或者model进行操作的时候 实例化query或者model都必须设置使用的QSqldatabase 其实就是设置连接名称
形如如下所示
QSqlQuery query(dbconn); query.exec(sql_string); return query;
或者
model= new QSqlTableModel(this,db->dbconn); model->setTable(tr("文字表")); model->select(); ui->tableView->setModel(model); ui->tableView->hideColumn(0);
model= new QSqlQueryModel(this); model->setQuery(tr("select 客户编号 from 客户表 "),db->dbconn);
其实也是一知半解 下面贴一下改造过的数据库连接类
h文件
#ifndef SQLITEDB_H #define SQLITEDB_H #include <QString> #include <QtSql> class SqliteDB { public: SqliteDB(QString connName); ~SqliteDB(); static void setDbName(QString name); static QString getDbName(); QStringList findDbfiles(); bool connDb(); QSqlQuery search(QString sql_string); void closeDb(); QSqlQuery query; QSqlDatabase dbconn; QString currentConnName; private: static QString DbName; }; #endif // SQLITEDB_H
cpp文件
#include "sqlitedb.h"
#include <QDir>
#include <QtSql>
#include <QString>
#include <QMessageBox>
QString SqliteDB::DbName="";
SqliteDB::SqliteDB(QString connName)
{
currentConnName=connName;
}
SqliteDB::~SqliteDB()
{
if(dbconn.isOpen()==true)
{
dbconn.close();
}
QSqlDatabase::removeDatabase(dbconn.connectionName());
}
void SqliteDB::setDbName(QString name)
{
SqliteDB::DbName=name;
}
QString SqliteDB::getDbName()
{
return DbName;
}
QStringList SqliteDB::findDbfiles()
{
QDir dir;
dir.setPath("./DbfInUse");
dir.setFilter(QDir::Files | QDir::Hidden);
dir.setSorting(QDir::Name);
QStringList names = dir.entryList();
QStringList newnames;
newnames=names.filter(".dbf");
return newnames;
}
bool SqliteDB::connDb()
{
if(!dbconn.isValid())
{
dbconn = QSqlDatabase::addDatabase("QSQLITE",currentConnName); dbconn.setDatabaseName("./DbfInUse/"+SqliteDB::DbName);
}
if(dbconn.isOpen()==true)
{
return true;
}
else
{
if(!dbconn.open())
{
return false;
}
else
{
return true;
}
}
}
QSqlQuery SqliteDB::search(QString sql_string)
{
QSqlQuery query(dbconn); query.exec(sql_string); return query;
}
void SqliteDB::closeDb()
{
if(dbconn.isOpen()==true)
{
dbconn.close();
}
}
相关文章推荐
- KAV6导致部分程序崩溃的解决办法(kernel32.dll相关)
- KAV6导致部分程序崩溃的解决办法(kernel32.dll相关)
- Qt实用技巧:使用QTableView、QSqlTableMode与QSqlDatabase对数据库数据进行操作
- Qt每日小结——解决使用setModel()后程序崩溃的问题
- Qt实用技巧:使用QTableView、QSqlTableMode与QSqlDatabase对数据库数据进行操作
- linux中修改环境变量之后导致系统崩溃(用户所有命令不能使用)的解决办法
- 使用了环境事务(TransactionScope) 跨库操作导致 服务器"xxxx" MSDTC 不可用解决办法
- Qt5 中使用了QQuickWidget,程序退出时容易崩溃的解决办法。
- golang在32位系统下atomic.AddUint64导致程序崩溃及解决办法
- 遇到当试图还原 master 数据库时,必须以单用户模式使用 RESTORE DATABASE.的解决办法
- CI使用Tank Auth转移数据库导致密码用户错误的解决办法
- iOS开发蓝牙固件升级使用iOSDFULibrary程序崩溃的解决办法
- 每次重启Tomcat后,使用Hibernate修改数据库的记录都会导致以前记录被删除的解决办法。
- 使用“一键清理垃圾”导致.Net程序无法运行的解决办法
- Qt 多线程与数据库操作需要注意的几点问题(QSqlDatabase对象只能在当前线程里使用)
- CI使用Tank Auth转移数据库导致密码用户错误的解决办法
- golang--- 32位系统下atomic.AddUint64导致程序崩溃及解决办法
- android.webkit.WebView 使用 SINGLE_COLUMN layout algorithm 导致程序意外退出的解决办法
- PHP中使用foreach和引用导致程序BUG及解决办法
- vc2010使用CMFCEditBrowseCtrl控件导致程序退出崩溃解决