QT开发(四十九)——数据库用户接口层

QT开发(四十九)——数据库用户接口层

    用户接口层主要包括Qt SQL模块中的QSqlQueryModelQSqlTableModelQSqlRelationalTableModel。用户接口层的类实现了将数据库中的数据连接到窗口部件上,是使用模型/视图框架实现的,是更高层次的抽象,即使不熟悉SQL也能够操做数据库。须要注意的是,在使用用户接口层的类以前必须先实例化QCoreApplication对象。数据库

    QT中使用了本身的机制来避免使用SQL语句,提供了更简单的数据库操做及数据显示模型,分别是只读的QSqlQueryModel、操做单表的QSqlTableModel和支持外键的QSqlRelationalTableModel框架

1、QSqlQueryModel

1QSqlQueryModel简介

    QSqlQueryModel类为SQL结果集提供了只读的数据模型,是执行SQL语句和遍历结果集的高级接口。QSqlQueryModel基于下层的QSqlQuery构建,用于提供数据给QTableView等视图类。ide

QSqlQueryModel模型默认是只读的,经过QSqlQueryModel派生自定义类重写setData()和flags()函数能够实现读写,或是使用QSqlTableModel函数

2QSqlQueryModel成员函数

QSqlQueryModel::QSqlQueryModel(QObject *parent = Q_NULLPTR)字体

使用给定的parent构建一个QSqlQueryModel空对象this

[virtual] void QSqlQueryModel::clear()spa

清除模型并释放申请的任何资源对象

void QSqlQueryModel::setQuery(const QSqlQuery &query)排序

重置模型并设置数据源为给定的queryQuery必须处于活跃状态继承

void QSqlQueryModel::setQuery(const QString &query, const QSqlDatabase &db = QSqlDatabase())

void QSqlQueryModel::setQuery(const QSqlQuery &query)

在给定的数据库链接db中执行查询query,若是数据库链接未指定或非法,使用默认的数据库链接

[protected] void QSqlQueryModel::setLastError(const QSqlError &error)

设置数据库发生的最后一个错误到error

[virtual] QVariant QSqlQueryModel::data(const QModelIndex &item, int role = Qt::DisplayRole) const

返回item数据项的role的值

3QSqlQueryModel实例

    QSqlQueryModel *model = new QSqlQueryModel;

    model->setQuery("select * from student");

    model->setHeaderData(0, Qt::Horizontal, tr("id"));

    model->setHeaderData(1, Qt::Horizontal, tr("name"));

    QTableView *view = new QTableView;

    view->setModel(model);

    view->show();

4、建立自定义QSqlQueryModel

    QSqlQueryModel默认是只读的,在窗口上并不能对表格中的内容进行修改。若是要按照本身的须要显示数据和修改数据,能够建立本身的模型。要想使其可读写,须要本身的类继承自QSqlQueryModel,而且重写setData()和flags()两个函数。若是要改变数据的显示,就要重写data() 函数。

Qt::ItemFlags flags(const QModelIndex &index) const;

bool setData(const QModelIndex &index, const QVariant &value, int role);

QVariant data(const QModelIndex &item, int role=Qt::DisplayRole) const;

SqlQueryModel.h文件:

#define SQLQUERYMODEL_H
 
#include <QSqlQueryModel>
#include <QObject>
#include <QModelIndex>
#include <QVariant>
#include <QString>
#include <QColor>
 
class SqlQueryModel : public QSqlQueryModel
{
    Q_OBJECT
public:
    SqlQueryModel(QObject *parent = 0);
 
protected:
    Qt::ItemFlags flags(const QModelIndex &index) const;
    bool setData(const QModelIndex &index, const QVariant &value, int role);
    QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const;
private:
    bool setName(int studentId, const QString &name);
    void refresh();
};
 
#endif // SQLQUERYMODEL_H

SqlQueryModel.cpp文件:

#

include "SqlQueryModel.h"
#include <QSqlQuery>
 
 
SqlQueryModel::SqlQueryModel(QObject *parent):QSqlQueryModel(parent)
{
}
 
Qt::ItemFlags SqlQueryModel::flags(const QModelIndex &index) const
{
    Qt::ItemFlags flags = QSqlQueryModel::flags(index);
    if (index.column() == 1) //第二个属性可更改
        flags |= Qt::ItemIsEditable;
    return flags;
}
 
bool SqlQueryModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (index.column() < 1 || index.column() > 2)
        return false;
    QModelIndex primaryKeyIndex = QSqlQueryModel::index(index.row(), 0);
    int id = data(primaryKeyIndex).toInt(); //获取id号
    clear();
    bool ok;
    if (index.column() == 1) //第二个属性可更改
        ok = setName(id, value.toString());
    refresh();
    return ok;
}
 
QVariant SqlQueryModel::data(const QModelIndex &index, int role) const
{
    QVariant value = QSqlQueryModel::data(index, role);
 
    //第一个属性的字体颜色为红色
    if (role == Qt::TextColorRole && index.column() == 0)
        return qVariantFromValue(QColor(Qt::red));
    return value;
}
 
bool SqlQueryModel::setName(int studentId, const QString &name)
{
    QSqlQuery query;
    query.prepare("update student set name = ? where id = ?");
    query.addBindValue(name);
    query.addBindValue(studentId);
    return query.exec();
}
 
void SqlQueryModel::refresh()
{
    setQuery("select * from student");
    setHeaderData(0, Qt::Horizontal, QObject::tr("id"));
    setHeaderData(1, Qt::Horizontal, QObject::tr("name"));
}

 

 

Main.cpp文件:

#include "SqlQueryModel.h"
#include <QApplication>
#include <QTableView>
#include <QSqlQueryModel>
#include <QSqlDatabase>
#include <QSqlQuery>
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(":memory:");
    if(!db.open())
        return false;
    QSqlQuery query;
    query.exec("create table student (id int primary key, name vchar)");
    query.exec("insert into student values (0,'scorpio')");
    query.exec("insert into student values (1,'alex')");
    query.exec("insert into student values (2,'alexander')");
 
    QSqlQueryModel *model = new QSqlQueryModel;
    model->setQuery("select * from student");
    model->setHeaderData(0, Qt::Horizontal, QObject::tr("id"));
    model->setHeaderData(1, Qt::Horizontal, QObject::tr("name"));
    QTableView *view = new QTableView;
    view->setModel(model);
    view->setWindowTitle("QSqlQueryModel");
    view->show();
 
    SqlQueryModel *mymodel = new SqlQueryModel;
    mymodel->setQuery("select * from student");
    mymodel->setHeaderData(0, Qt::Horizontal, QObject::tr("id"));
    mymodel->setHeaderData(1, Qt::Horizontal, QObject::tr("name"));
    QTableView *view1 = new QTableView;
    view1->setWindowTitle("SqlQueryModel"); //修改窗口标题
    view1->setModel(mymodel);
    view1->show();
    return a.exec();
}

 

 

2、QSqlTableModel

1QSqlTableModel简介

    QSqlTableModel提供了一个一次只能操做单个SQL表的读写模型,它是QSqlQuery的更高层次的替代品,能够浏览和修改独立的SQL表,而且只需编写不多的代码,并且不须要了解SQL语法。

    QSqlTableModel类为单个数据库表提供了可编辑的数据模型,是从单个表中读写数据库记录的高级接口。QSqlTableModel基于下层的QSqlQuery构建,用于提供数据给QTableView等视图类。

2QSqlTableModel成员函数

QSqlTableModel::QSqlTableModel(QObject *parent = Q_NULLPTR, QSqlDatabase db = QSqlDatabase())

构建一个QSqlTableModel空对象,设置父对象为parent,数据库链接为db,若是db非法,使用默认数据库链接。

[signal] void QSqlTableModel::beforeDelete(int row)

[signal] void QSqlTableModel::beforeInsert(QSqlRecord &record)

[signal] void QSqlTableModel::beforeUpdate(int row, QSqlRecord &record)

QSqlDatabase QSqlTableModel::database() const

返回模型的数据库链接

[virtual protected] bool QSqlTableModel::deleteRowFromTable(int row)

从当前活跃的数据库表中删除给定的行

EditStrategy QSqlTableModel::editStrategy() const

返回当前的编辑策略

int QSqlTableModel::fieldIndex(const QString &fieldName) const

返回字段名为fieldName的字段的索引,若是没有相应字段返回-1

QString QSqlTableModel::filter() const

返回当前设置的过滤器

bool QSqlTableModel::insertRecord(int row, const QSqlRecord &record)

row行插入一条记录record,若是row为负数,追加到尾部

bool QSqlTableModel::isDirty(const QModelIndex &index) const

若是index位置的值是脏值,返回true。脏值是被模型修改单还没有写入数据库的值

bool QSqlTableModel::isDirty() const

若是模型包含被修改的值而且没有提交到数据库,返回true

QSqlIndex QSqlTableModel::primaryKey() const

返回当前表的主键

3QSqlTableModel使用

#include <QApplication>
#include <QSqlTableModel>
#include <QTableView>
#include <QSqlDatabase>
#include <QSqlQuery>
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(":memory:");
    if(!db.open())
        return false;
    QSqlQuery query;
    query.exec("create table student (id int primary key, name vchar)");
    query.exec("insert into student values (0,'scorpio')");
    query.exec("insert into student values (1,'alex')");
    query.exec("insert into student values (2,'alexander')");
 
    QSqlTableModel *model = new QSqlTableModel;
    model->setTable("student");
    model->setEditStrategy(QSqlTableModel::OnManualSubmit);
    model->select(); //选取整个表的全部行
 
    QTableView *view = new QTableView;
    view->setModel(model);
    view->show();
 
    return a.exec();
}

    A、修改操做

提交修改

//开始事务操做
model->database().transaction();
if (model->submitAll())
{
    model->database().commit(); //提交
}
else
{
    model->database().rollback(); //回滚
    QMessageBox::warning(this, tr("tableModel"),
                 tr("数据库错误: %1").arg(model->lastError().text()));
}

撤销修改

model->revertAll();

    B、查询操做

QString name = lineedit->text();

//根据姓名进行筛选

model->setFilter(QString("name = '%1'").arg(name));

//显示结果

model->select();

 

model->setTable("student"); //从新关联表

model->select();//选择整个表格

    C、排序操做

升序:

model->setSort(0, Qt::AscendingOrder); //id属性即第0列,升序排列

model->select();

降序:

model->setSort(0, Qt::DescendingOrder);

model->select();

    D、删除操做

//获取选中的行

int curRow = view->currentIndex().row();

//删除该行

model->removeRow(curRow);

int ok = QMessageBox::warning(this,tr("删除当前行!"),tr("你肯定删除当前行吗?"),QMessageBox::Yes,QMessageBox::No);

if(ok == QMessageBox::No)

{

    model->revertAll(); //若是不删除,则撤销

}

else

    model->submitAll(); //不然提交,在数据库中删除该行

E、插入操做

int rowNum = model->rowCount(); //得到表的行数

int id = 10;

model->insertRow(rowNum); //添加一行

model->setData(model->index(rowNum,0),id);

3、QSqlRelationalTableModel

1QSqlRelationalTableModel简介

    QSqlRelationalTableModel为了单个数据库表格提供了可编辑的数据模型。

QSqlRelationalTableModel继承自QSqlTableModel,并对其进行了扩展,提供了对外键的支持。外键就是一个表中的一个属性和其余表中的主键属性之间的一对一的映射。

二、QSqlRelationalTableModel成员函数

[virtual] void QSqlRelationalTableModel::setRelation(int column, const QSqlRelation &relation)

当前表中第column列为QSqlRelation(tableName,indexColumn,displayColumn)的外键

QVariant QSqlRelationalTableModel::data(const QModelIndex &index, int role = Qt::DisplayRole) const

返回index的数据

[virtual protected] bool QSqlRelationalTableModel::insertRowIntoTable(const QSqlRecord &values)

向表中插入一条记录values

QSqlRelation QSqlRelationalTableModel::relation(int column) const

返回表格中第column列的关系

[virtual] QSqlTableModel *QSqlRelationalTableModel::relationModel(int column) const

返回外键column要访问的表的QSqlTableModel对象

[virtual] bool QSqlRelationalTableModel::setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole)

设置index数据项的值为value,数据项角色为role

[virtual] void QSqlRelationalTableModel::setTable(const QString &table)

设置模型的表格为table

3、使用外键

#include<QSqlRelationalTableModel>
#include <QApplication>
#include <QTableView>
#include <QSqlDatabase>
#include <QSqlQuery>
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(":memory:");
    if(!db.open())
        return false;
    QSqlQuery query;
    query.exec("create table student (id int primary key, name vchar, course int)");
    query.exec("insert into student values(1,'scorpio',1)");
    query.exec("insert into student values(2,'alex',1)");
    query.exec("insert into student values(3,'alexandar',3)");
 
    query.exec("create table course (id int primarykey, name vchar, teacher vchar)");
    query.exec("insert into course values(1,'Math','kim')");
    query.exec("insert into course values(2,'English','kim')");
    query.exec("insert into course values(3,'Computer','kim')");
 
    QSqlRelationalTableModel *model = new QSqlRelationalTableModel;
    //属性变化时写入数据库
    model->setEditStrategy(QSqlTableModel::OnFieldChange);
    model->setTable("student");
    //将student表的第2个属性设为course表的id属性的外键,
    //并将其显示为course表的name属性的值
    model->setRelation(2,QSqlRelation("course","id","name"));
    model->setHeaderData(0, Qt::Horizontal, QObject::tr("ID"));
    model->setHeaderData(1, Qt::Horizontal, QObject::tr("Name"));
    model->setHeaderData(2, Qt::Horizontal, QObject::tr("Course"));
    model->select();
    QTableView *view = new QTableView;
    view->setModel(model);
    view->show();
 
    return a.exec();
}

4、使用委托

为了控制表中某些数据项的数据的可选类型或是数据内容,可使用委托。QT提供了QSqlRelationalDelegate委托类,能够为QSqlRelationalTableModel显示和编辑数据。不一样于默认的委托,QSqlRelationalDelegate为外键提供了字段的下拉框。

view->setItemDelegate(new QSqlRelationalDelegate(view));

相关文章
相关标签/搜索