本文逐步介绍QT,VS和FireBird.适用于打算使用嵌入式FireBird的QT开发者以及QT新手.在我写这篇文档的时候,有关本文涉及的话题还在大量的讨论,所以我希望本文能对大家有所帮助.
1. 安装QT SDK,并与VS进行配置整合.
2. Building IBase插件.
3. 使用代码创建一个数据库并设置其连接.
4. 同时也讨论数据库的用户名和密码问题.
5. 创建一个简单的查询及调用存储过程.
下面描述的范例基于QT 4.5.2 LGPL.
按如下步骤设置开发环境.
1) 有足够的磁盘空间 (要编译所有库和范例需要2-3 GB,否则1.5 GB).
2)安装SDK: QTSDK 4.5.2
推荐不要修改默认的安装路径(或在其他盘符的相同路径下,如"D:\").
3) 创建环境变量"QTDIR"值为"C:\Qt\2009.03\qt\" (步骤2为默认).
1) 启动"VS 2005 Command Prompt" (开始菜单)
2) 在控制台上设置当前目录QTDIR = "C:\Qt\2009.03\qt\"
3) 使用下面命令行启动"configure.exe":
configure.exe -plugin-sql-ibase.(注意后面的参数没有空格)
可使用下面命令查看每个参数的详细信息:
configure.exe -help
4) 然后控制台询问:要使用哪个版本的QT?(Which edition of Qt do you want to use?)选择Open Source版本.
按Y键确认授权信息.
5) 现在需要等一会才能将VCProj文件和主解决方案创建出来.最后在C:\Qt\2009.03\qt目录下生成projects.sln解决方案文件
1) 关闭所有VS应用.
2) 启动qt-vs-addin-1.0.2.exe 安装程序
3) 启动VS,点击QT选项("QT->QT Options").点击并输入QT版本号名称如"QT 4.5.2".这里的名称并不重要,但是其将存储在项目文件中,因此其他开发者可能在生成项目的时候报错: ("No such QT version is found on this machine" or something like this).
指定Qt路径,本例为$(QTDIR)("C:\Qt\2009.03\qt\"). 最后选择新创建的记录"QT 4.5.2"作为默认版本.
4) 不需要生成全部项目.只需要生成:
· QtCore
· QtGUI
· QtSQl
· QMain
注意: Win32静态库和QT库对"Treat wchar_t as Built-In"属性有不同的设置.如果想在QT应用程序中使用Win32静态库,需要将这个属性去除或改为No("Treat wchar_t as Built-In Type"为"No(/Zc:wchar_t-)".
要关掉这个选项,需要在步骤2之前进行如下操作:
· 打开qmake.conf文件,可在QTDIR/mkspecs/win32-msvc2005/qmake.conf目录中找到.我使用VS2005因此选择子目录win32-msvc2005中的文件.如果你使用其他版本要选择相应的目录文件.
· 在这个文件中修改QMAKE_CFLAGS标记,删除-Zc:wchar_t-.
Firebird下载地址– FireBird.
进入目录$(QTDIR)\src\plugins\sqldrivers\ibase ,并在Debug和Release模式下Build项目.
生成之前修改如下项目属性:
· 在 C/C++/General->Additional Include Directories 添加包含路径(如C:\Program Files\Firebird\Firebird_2_1\include)
· 在Linker/General -> Additional Library Directories 添加FireBird库路径.(如C:\Program Files\Firebird\Firebird_2_1\lib)
· 要生成IBase项目我们需要修正链接库名称(Linker/Input->Additional Dependencies),将gds32_ms.lib调整为fbclient_ms.lib .库包含在FireBird包中.
嵌入式服务器下载地址: FireBird Embedded 2.1.3 Release
· 修改fbembed.dll文件名为fbclient.dll.
在设置数据库连接之前,我们首先需要加载QIBASE插件.如果你要使用插件并手动加载,可以使用如下代码(假定插件与Exe文件同目录).
…
if(!pluginLoader_.isLoaded())
{
pluginLoader_.setFileName(QApplication::instance()->applicationDirPath() +
QDir::separator() + qtIBasePluginName_);
if (!pluginLoader_.load())
{
//// Loading SQL Driver failed.;
isInitialized_ = false;
return false;
}
}
QObject* object = pluginLoader_.instance();
if (object == NULL)
{
//Loading SQL Driver Instance failed.;
pluginLoader_.unload();
return false;
}
QSqlDriverPlugin* plugin = qobject_cast<QSqlDriverPlugin*>(object);
if (plugin == NULL)
{
//QSqlDriverPlugin == NULL;
pluginLoader_.unload();
return false;
}
driver_ = plugin->create("QIBASE");
if (driver_ == NULL)
{
//Loading QIBASE Driver Instance failed.;
pluginLoader_.unload();
return false;
}
isInitialized_ = true;
return isInitialized_;
…
FireBird支持插件加载后,就可以开始连接数据库了.
connectionName_ = "Connection_1";
QSqlDatabase database;
//Adding database (DRIVER);
database = QSqlDatabase::addDatabase(driver_, connectionName_);
//Check Valid database.;
if (!database.isValid())
{
QString lastError = database.lastError().text();
//Database is not valid
return false;
}
//Set database configurations.;
// filePath = ":D:\FireBirdAndQT\debug\New.FDB";
// userName = "Serg";
// password = 12345;
// connectionString_ = "server type=Embedded; auto_commit=True;
// auto_commit_level=4096; connection lifetime=1; DataBase=\"%1\"";
database.setDatabaseName(filePath);
database.setUserName(userName);
database.setPassword(password);
QString connectionString = QString(connectionString_).arg(filePath);
database.setConnectOptions(connectionString);
bool result = false;
//"Openning database. Driver PTR == %d", (int)database.driver();
result = database.open();
if(!result)
{
QString lastError = database.lastError().text();
lastError_ = (uint)database.lastError().number();
}
希望可以对QSqlDatabase如下几个属性加以注意:
database.setDatabaseName(filePath);
database.setUserName(userName);
database.setPassword(password);
QString connectionString = QString(connectionString_).arg(filePath);
database.setConnectOptions(connectionString);
登录名,密码和完整路径需要包含在连接字符串中,但是有如下几个问题:我将上面提到的几个设置加入到连接字符串中,而没有使用set…()函数,我发现这些值没有设置到数据库对象.
使用代码创建数据库须如下代码:
bool FireBirdDatabase::Create(const QString& filePath, const QString& userName, const QString& password)
{
if (!isInitialized_)
{
Initialize();
}
if (QFile::exists(filePath))
{
return false;
}
databasePath_ = filePath;
QString queryString;
queryString += "CREATE DATABASE";
queryString += " \'" + filePath + "\'";
queryString += " USER \'" + userName + "\'";
queryString += " PASSWORD \'" + password + "\'";
queryString += " DEFAULT CHARACTER SET UNICODE_FSS";
ISC_STATUS_ARRAY status;
isc_db_handle databaseHandle = NULL;
isc_tr_handle transactionHandle = NULL;
unsigned short g_nFbDialect = SQL_DIALECT_V6;
if (isc_dsql_execute_immediate(status, &databaseHandle, &transactionHandle, 0, queryString.toStdString().c_str (), g_nFbDialect, NULL))
{
long SQLCODE=isc_sqlcode(status);
return false;
}
isc_commit_transaction( status, &transactionHandle );
if (databaseHandle != NULL)
{
ISC_STATUS_ARRAY status;
isc_detach_database(status, &databaseHandle);
}
return true;
}
为什么使用isc_dsql_execute_immediate()函数创建数据库?答案是我不能使用其他方式.一些供应商允许如下方式创建数据库:
…
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(":memory:");
if (!db.open())
{
QMessageBox::critical(0, qApp->tr("Cannot open database"),
qApp->tr("Unable to establish a database connection.\n"
"This example needs SQLite support. Please read "
"the Qt SQL driver documentation for information how "
"to build it.\n\n"
"Click Cancel to exit."), QMessageBox::Cancel);
return false;
}
…
但是 通常QT版本和IBASE驱动不支持这种方式.
更多信息可以查看QT范例 (QTDIR\examples\sql\Connection.h).
注意: 小心- FireBird只支持ASCII编码.如果你的路径中包括Unicode字符isc_dsql_execute_immediate函数将报错.
void DatabaseModel::SelectJobs(QStringList& jobs )
{
QSqlQuery query = QSqlQuery(fireBirdDatabase_.CreateQuery());
QString preparedString = "SELECT JOB_NAME FROM TBL_JOBS";
query.prepare(preparedString);
if (!query.exec())
{
QString err = query.lastError().text();
throw std::runtime_error("Error executing Query.");
}
while (query.next())
{
QSqlRecord record = query.record();
jobs.append(record.value(0).toString());
}
}
fireBirdDatabase_.CreateQuery()实现如下:
{
return QSqlQuery(QSqlDatabase::database(connectionName_));
}
考虑一个典型的范例-调用向数据库中添加一条记录的存储过程.
存储过程包含的参数:一个字符串位置名称,整数工资,BLOB的描述信息.
存储过程返回新纪录的ID.
{
…
QByteArray description("Test description");
int salary = 1200;
jobName = "tester";
QSqlQuery query(fireBirdDatabase_.CreateQuery());
bool result = query.prepare("EXECUTE PROCEDURE SP_INSERT_JOB (?, ?, ?)");
query.addBindValue(jobName);
query.addBindValue(salary);
query.addBindValue(description);
if (!query.exec())
{
QString err = query.lastError().text();
throw std::runtime_error("Error executing Query.");
}
query.next();
int jobID = query.value(0).toUInt();
…
}
希望本文可以帮助你:
为进一步工作配置QT环境.
为使用FireBird生成插件.
连接到已存在的数据库或使用程序新建一个.
执行各种查询.
我以将测试数据库和代码上传.
查看数据库可以使用如下客户端工具:
· IBExpert
测试数据库用户名和密码分别为Serg,12345.
· FlameRobin (开源管理工具).
· IBExpert (administration tool, free Personal Edition download).
作者:henreash