QSqlRelationalTableModelを使用してQtのデータベースの操作を簡素化する

こんにちは、ハブロフスク! この記事では、QtクロスプラットフォームライブラリのQSqlRelationalTableModelクラスを使用してデスクトップアプリケーションを開発する際に、SQLデータベースとの対話を簡素化した私の経験についてお話したいと思います。

プロローグ


私は、C ++でプログラミングを始めたばかりの1年生のときにQtに出会いました。それから、ライブラリに真剣に興味を持ち、それ以来、その更新を追ってきました。 数か月前、職場で、彼らは私にTORを提供しました。TORでは、SQLiteデータベースとやり取りするアプリケーションを開発する必要がありました。 ベースの構造は固定されており、TKから事前にわかっています。

アプリケーションは、新しいレコードの追加、既存のレコードの削除および変更を可能にするために、オペレーターがデータベースに保存されたデータを表示できるようにする必要があります。

次に、コードスニペットを使用して開発プロセスを簡単に説明し、この場合はQSqlRelationalTableModelを優先して選択した理由を合理的に説明します。

開発開始


最初は、単純なデータベースクエリを使用してデータベースとの対話を確立することが決定されました。 SELECTINSERTDELETE 。これにより、アプリケーションに必要なすべての機能を実装できます。

これを行うには、 QSqlDatabaseクラスQSQlQueryクラスが必要です。

QSqlDatabase db; //    db = QSqlDatabase::addDatabase("QSQLITE"); //    db.setHostName("localhost"); //  ,    db.setDatabaseName(path); //QString path -    //   if(db.open()){ qDebug() << "db opened OK..."; }else{ qDebug() << " db opening failed..."; } }else{ qDebug() << "file doesnot exist"; exit(0); // ,     , //   } 

その後、データベースに対するすべての操作が次のように実行されます。

 // ,    <b>QLineEdit</b>' QString query = "INSERT INTO Table (column) VALUES ('" + ui->Input->text() + "')"; QSqlQuery sqlQuery(db); //c   qDebug() << "QUERY: " << query; // //   if(sqlQuery.exec(query)){ qDebug() << "query failed..."; } else{ qDebug() << "query failed..."; } 

Selectステートメントも同様に実行されますが、データを受信して​​どこかに置く必要がある点が異なります。

 QString query = "SELECT id, ka FROM Table"; QSqlQuery sqlQ(db); if(!sqlQ.exec(query)) { qDebug() << "query failed..."; return; } //     // ,        while (sqlQ.next()){ //           ui->ComboBox->addItem(sqlQ.value(1).toString(),sqlQ.value(0).toInt()); } 

削除ステートメントは、何も返さないため、Insertとまったく同じ方法で実行されます。

大丈夫、問題は何ですか?


そして真実は、これらの式とクエリを通じてすべてを実装できるということです。 なぜモデルが必要なのでしょうか?

関係のないテーブルが1つある場合、すべてが非常に単純に見えるため、追加のツールを導入する必要はありません。 今、そのようなテーブル、たとえば、idを含まない5つのカラムを持つ5つのテーブルがあると想像してください。 そして、それぞれがidを介して外部キーを使用して前のものと接続しています 。 削除するときは、カスケードしてすべての「子」レコードを削除する必要があります。 これにより、膨大な数のリクエストが発生し、アプリケーションの動作が遅くなり、さらに毎回インターフェイスのテーブルとその表示を更新する必要があり、更新のための追加機能の作成、バグの出現、またはそれらの発生のリスク、一般的に読みやすさの低下につながりますコード。

このため、開発プロセス中に、ベアSQLクエリを使用するという概念を放棄する必要がありました。

QTableViewとともにQSqlRelationalTableModelを選択して、さらに選択を行いました。 モデル実装のさらにシンプルなバージョンがあります-QSqlTableModel 、最初のものはそれから継承され、すべて同じメソッドを持っていますが、 QSqlRelation接続を作成する機能を追加します。これは、ユーザーがレコードID接続されています。

モデルを使用した実装を見てみましょう


モデル/ビューの実装を示すポッドの抜粋を次に示します。

ヘッダーファイル:

 QSqlRelationalTableModel *model; 

コンストラクター内:

 //  ,    //  QTableView  ,    //QModelIndex     ,      connect(ui->tableView, SIGNAL(clicked(const QModelIndex &)), this, SLOT(onTableClicked(const QModelIndex &))); model = new QSqlRelationalTableModel(parent, db); // , QSqlDatabase    model->setTable("Table"); //    

以下の行には、SQLクエリに対するモデルの最も便利な機能と利点の1つが含まれています-コンテキストに応じて、QTableViewに変更するときにSQLテーブルのデータを編集、追加、削除します。 便利なのは、カスケードデータ削除の正確性を制御し、単一のQTableViewのフレームワーク内で更新する必要がなくなることです。

 model->setEditStrategy(QSqlRelationalTableModel::OnFieldChange); 

次に、このクラスが提供する別の便利な機能があります。異なるテーブルの2つの列の間に接続が確立されます。

 //ParentTable - ,      //id - ,         //name - ,        model->setRelation(1,QSqlRelation("ParentTable", "id", "name")); 

さらに、すべてがより標準的です。select()はSELECTステートメントを実行し、setHeaderData()はQTableViewヘッダーにテキストを設定します。

 model->select(); model->setHeaderData(0, Qt::Horizontal, tr("id")); model->setHeaderData(1, Qt::Horizontal, tr("id_sub")); model->setHeaderData(2, Qt::Horizontal, tr("count")); model->setHeaderData(3, Qt::Horizontal, tr("number")); model->setHeaderData(4, Qt::Horizontal, tr("data_word")); model->setHeaderData(5, Qt::Horizontal, tr("time")); model->setHeaderData(6, Qt::Horizontal, tr("name")); model->setHeaderData(7, Qt::Horizontal, tr("description")); ui->tableView->setModel(model); //     QTableView 

これで、モデルとtableViewが連携して機能します。 githubへのリンクはすべてのソースを残します。その中に、モデルへのエントリの追加、削除、およびフィルターを実装しました。

おわりに


この記事では、すでにQtでデータベースを操作しているすべての人に、少なくとも中程度の複雑さのプロジェクトの裸のSQLクエリを放棄し、モデルの操作に切り替えて、生活を簡素化し、コードをより読みやすく、普遍的にすることを奨励したかったのです。良いことや新しいことをしてください。

それだけです! これらのクラスでの私の経験が、読者が同様の問題をうまく解決するのに役立つことを願っています!

Source: https://habr.com/ru/post/J435134/


All Articles