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));

相關文章
相關標籤/搜索