Spec-Zone.ru › Qt 5.9

Использование классов модели SQL

Помимо QSqlQuery, Qt предлагает три класса более высокого уровня для доступа к базам данных. Этими классами являются QSqlQueryModel, QSqlTableModel и QSqlRelationalTableModel.

QSqlQueryModel Модель только для чтения, основанная на произвольном запросе SQL.
QSqlTableModel Модель чтения/записи, которая работает с одной таблицей.
QSqlRelationalTableModel Подкласс QSqlTableModel с поддержкой внешних ключей.

Эти классы наследуются от QAbstractTableModel (который, в свою очередь, наследуется от QAbstractItemModel) и упрощают представление данных из базы данных в классе представления элементов, таком как QListView и QTableView. Это подробно описано в разделе Представление данных в представлении таблицы.

Еще одним преимуществом использования этих классов является то, что ваш код может быть легче адаптирован к другим источникам данных. Например, если вы используете QSqlTableModel, а затем решите использовать XML-файлы для хранения данных вместо базы данных, это в основном сводится к замене одной модели данных другой.

Модель запроса SQL

QSqlQueryModel предлагает модель только для чтения, основанную на запросе SQL.

Пример:

    QSqlQueryModel model;
    model.setQuery("SELECT * FROM employee");

    for (int i = 0; i < model.rowCount(); ++i) {
        int id = model.record(i).value("id").toInt();
        QString name = model.record(i).value("name").toString();
        qDebug() << id << name;
    }

После установки запроса с помощью QSqlQueryModel::setQuery(), вы можете использовать QSqlQueryModel::record(int) для доступа к отдельным записям. Вы также можете использовать QSqlQueryModel::data() и любые другие функции, унаследованные от QAbstractItemModel.

Также существует перегрузка setQuery(), которая принимает объект QSqlQuery и работает с его набором результатов. Это позволяет использовать любые возможности QSqlQuery для настройки запроса (например, подготовленные запросы).

Модель таблицы SQL

QSqlTableModel предлагает модель чтения/записи, которая работает с одной таблицей SQL за раз.

Пример:

    QSqlTableModel model;
    model.setTable("employee");
    model.setFilter("salary > 50000");
    model.setSort(2, Qt::DescendingOrder);
    model.select();

    for (int i = 0; i < model.rowCount(); ++i) {
        QString name = model.record(i).value("name").toString();
        int salary = model.record(i).value("salary").toInt();
        qDebug() << name << salary;
    }

QSqlTableModel — это высокоуровневая альтернатива QSqlQuery для навигации и изменения отдельных таблиц SQL. Как правило, это приводит к меньшему коду и не требует знаний синтаксиса SQL.

Используйте QSqlTableModel::record() для получения строки в таблице и QSqlTableModel::setRecord() для изменения строки. Например, следующий код увеличит зарплату каждого сотрудника на 10 процентов:

    for (int i = 0; i < model.rowCount(); ++i) {
        QSqlRecord record = model.record(i);
        double salary = record.value("salary").toInt();
        salary *= 1.1;
        record.setValue("salary", salary);
        model.setRecord(i, record);
    }
    model.submitAll();

Вы также можете использовать QSqlTableModel::data() и QSqlTableModel::setData(), которые унаследованы от QAbstractItemModel, для доступа к данным. Например, вот как обновить запись с помощью setData():

    model.setData(model.index(row, column), 75000);
    model.submitAll();

Вот как вставить строку и заполнить её:

    model.insertRows(row, 1);
    model.setData(model.index(row, 0), 1013);
    model.setData(model.index(row, 1), "Peter Gordon");
    model.setData(model.index(row, 2), 68500);
    model.submitAll();

Вот как удалить пять последовательных строк:

    model.removeRows(row, 5);
    model.submitAll();

Первый аргумент QSqlTableModel::removeRows() — это индекс первой удаляемой строки.

После внесения изменений в запись всегда следует вызывать QSqlTableModel::submitAll(), чтобы убедиться, что изменения записаны в базу данных.

Нужно ли и когда вызывать submitAll() зависит от стратегии редактирования таблицы edit strategy. По умолчанию используется стратегия QSqlTableModel::OnRowChange, которая определяет, что ожидаемые изменения применяются к базе данных, когда пользователь выбирает другую строку. Другими стратегиями являются QSqlTableModel::OnManualSubmit (где все изменения кешируются в модели до вызова submitAll()) и QSqlTableModel::OnFieldChange (где изменения не кешируются). Они в основном полезны, когда QSqlTableModel используется с представлением.

QSqlTableModel::OnFieldChange кажется, выполняет обещание, что вам никогда не нужно явно вызывать submitAll(). Однако есть две ловушки:

  • Без кеширования производительность может значительно снизиться.
  • Если вы изменяете первичный ключ, запись может быть потеряна, пока вы пытаетесь заполнить её.

Модель реляционной таблицы SQL

QSqlRelationalTableModel расширяет QSqlTableModel, чтобы обеспечить поддержку внешних ключей. Внешний ключ — это однозначное соответствие между полем в одной таблице и полем первичного ключа другой таблицы. Например, если таблица book имеет поле, называемое authorid, которое ссылается на поле id таблицы авторов, мы говорим, что authorid является внешним ключом.

На левом снимке показана обычная QSqlTableModel в QTableView. Внешние ключи (city и country) не разрешаются в удобочитаемые значения. На правом снимке показана QSqlRelationalTableModel, где внешние ключи разрешены в удобочитаемые текстовые строки.

Следующий фрагмент кода демонстрирует, как была настроена QSqlRelationalTableModel:

    model->setTable("employee");

    model->setRelation(2, QSqlRelation("city", "id", "name"));
    model->setRelation(3, QSqlRelation("country", "id", "name"));

Подробности см. в документации QSqlRelationalTableModel.

© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/archives/qt-5.6/sql-model.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API