Spec-Zone.ru › Qt

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

Spec-Zone.ru

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