Spec-Zone.ru › Qt 5.13

Использование моделей 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() зависит от стратегии редактирования таблицы. По умолчанию используется стратегия QSqlTableModel::OnRowChange, которая определяет, что ожидаемые изменения применяются к базе данных, когда пользователь выбирает другую строку. Другие стратегии — QSqlTableModel::OnManualSubmit (где все изменения кешируются в модели до тех пор, пока вы не вызовете submitAll()) и QSqlTableModel::OnFieldChange (где никакие изменения не кешируются). Они в основном полезны, когда QSqlTableModel используется с представлением.

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

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

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

QSqlRelationalTableModel расширяет QSqlTableModel, чтобы обеспечить поддержку внешних ключей. Внешний ключ — это отображение 1 к 1 между полем в одной таблице и полем первичного ключа другой таблицы. Например, если таблица 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/qt-5.13/sql-model.html

Spec-Zone.ru

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