背景知识:
Qt SQL的API分为不同层:
- 驱动层
驱动层 对于QT是基于C++来实现的框架,该层主要包括QSqlDriver、QSqlDriverCreator、QSqlDriverCreatorbase、QSqlDriverPlugin and QSqlResult。这一层提供了特定数据库和SQL API层之间的底层桥梁。
- SQL API层
SQL API层 对于SQL API 层提供了数据库的访问相关类,其中,QSqlDataBase类进行连接,QSqlQuery完成数据库的交互。除此之外,还有QSqlError、QSqlField、QSqlIndex and QSqlRecord类。
- 用户接口层
用户接口层 用户接口层的几个类实现将数据库中的数据链接到窗口部件上,这些类是使用模型/视图框架实现的,他们是更高层次的抽象,主要包括QSqlQureyModel,QSqlTableModel and QSqlRelationalTableModel。
用户接口层的类使用模型/视图框架实现了将数据库中的数据链接到窗口控件上。
QTableView是常用的内容显示视图组件。数据模型类有:QSqlQueryModel 、QSqlTableModel 、QSqlRelationalTableModel
QSqlQueryModel :通过设置SELECT语句查询获取内容,Model数据是只读的,不能进行编辑。
QSqlTableModel : 直接设置一个数据表的名称,可以获取数据表的全部记录,结果是可编辑的。
QSqlRelationalTableModel: 编辑一个数据表,将代码字段通过关系与代码表关联,将代码字段的编辑转换为直观的内容选择编辑。
QSqlRelationalTableModel
QSqlRelationalTableModel为QSqlTableModel 的子类,为单张的数据库表提供了一个可编辑的数据模型,它支持外键
即将主表里的某个字段存储为代码型字段,而代码的具体意义存储在另外一个数据表里。
主表代码字段和关联数据表的关联通过setRelation函数实现。
//关联函数
virtual void setRelation(int column, const QSqlRelation &relation);
QSqlRelation(const QString &aTableName, const QString &indexCol,
const QString &displayCol)
Column:主表的代码字段的序号
QSqlRelation
aTableName :代码表
indexCol:代码字段名称
displayCol:代码意义的字段名称
如
tabModel->setRelation(3,QSqlRelation("departments","departID","department")); //学院 tabModel->setRelation(4,QSqlRelation("majors","majorID","major"));//专业
例子
- 数据库使用SQLite数据库,格式为.db3
- 模型使用QSqlRelationalTableModel,视图使用QTableView
- 因为QSqlRelationalTableModel可编辑,可使用代理处理编辑操作。
- 除了关联字段特殊处理外,其他的和QSqlTableModel一样的操作。
打开数据库
void MainWindow::on_actOpenDB_triggered()
{QString aFile=QFileDialog::getOpenFileName(this,"选择数据库文件","","SQL Lite数据库(*.db *.db3)");// QString aFile= QFileDialog::getOpenFileName(this,"选择数据库文件","","SQL Lite数据库(*.db *.db3)");if (aFile.isEmpty())return;//打开数据库DB=QSqlDatabase::addDatabase("QSQLITE"); //添加 SQL LITE数据库驱动DB.setDatabaseName(aFile); //设置数据库名称
// DB.setHostName();
// DB.setUserName();
// DB.setPassword();if (!DB.open()) //打开数据库{
// QMessageBox::warning(this, "错误", "打开数据库失败",QMessageBox::Ok,QMessageBox::NoButton);return;}//打开数据表openTable();
}
打开数据表
void MainWindow::openTable()
{//打开数据表tabModel=new QSqlRelationalTableModel(this,DB);tabModel->setTable("studInfo"); //设置数据表tabModel->setEditStrategy(QSqlTableModel::OnManualSubmit); //OnManualSubmit , OnRowChangetabModel->setSort(0,Qt::AscendingOrder);tabModel->setHeaderData(0,Qt::Horizontal,"学号");tabModel->setHeaderData(1,Qt::Horizontal,"姓名");tabModel->setHeaderData(2,Qt::Horizontal,"性别");tabModel->setHeaderData(3,Qt::Horizontal,"学院");tabModel->setHeaderData(4,Qt::Horizontal,"专业");//设置代码字段的查询关系数据表tabModel->setRelation(3,QSqlRelation("departments","departID","department")); //学院tabModel->setRelation(4,QSqlRelation("majors","majorID","major"));//专业theSelection=new QItemSelectionModel(tabModel);connect(theSelection,SIGNAL(currentChanged(QModelIndex,QModelIndex)),this,SLOT(on_currentChanged(QModelIndex,QModelIndex)));ui->tableView->setModel(tabModel);ui->tableView->setSelectionModel(theSelection);ui->tableView->setItemDelegate(new QSqlRelationalDelegate(ui->tableView)); //为关系型字段设置缺省代理组件tabModel->select(); //打开数据表// ui->tableView->resizeColumnsToContents();
// ui->tableView->horizontalHeader()->setStretchLastSection(true);ui->actOpenDB->setEnabled(false);ui->actRecAppend->setEnabled(true);ui->actRecInsert->setEnabled(true);ui->actRecDelete->setEnabled(true);ui->actFields->setEnabled(true);
}
添加操作
void MainWindow::on_actRecAppend_triggered()
{//添加记录tabModel->insertRow(tabModel->rowCount(),QModelIndex()); //在末尾添加一个记录QModelIndex curIndex=tabModel->index(tabModel->rowCount()-1,1);//创建最后一行的ModelIndextheSelection->clearSelection();//清空选择项theSelection->setCurrentIndex(curIndex,QItemSelectionModel::Select);/
}
删除
void MainWindow::on_actRecDelete_triggered()
{//删除当前记录tabModel->removeRow(theSelection->currentIndex().row());tabModel->submitAll(); //立即更新
}
保存
void MainWindow::on_actSubmit_triggered()
{//保存修改bool res=tabModel->submitAll();if (!res)QMessageBox::information(this, "消息", "数据保存错误,错误信息\n"+tabModel->lastError().text(),QMessageBox::Ok,QMessageBox::NoButton);else{ui->actSubmit->setEnabled(false);ui->actRevert->setEnabled(false);}
}
取消修改
void MainWindow::on_actRevert_triggered()
{//取消修改tabModel->revertAll();ui->actSubmit->setEnabled(false);ui->actRevert->setEnabled(false);
}