MochiuWiki : SUSE, EC, PCB
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
Qtの基礎 - データベースのソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
Qtの基礎 - データベース
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == Qtでデータベース操作を行う場合、QtSqlモジュールが必要である。<br> <br> QtSqlモジュールはデータベース操作のための機能を提供するQtのコンポーネントであり、<br> QSqlDatabase、QSqlQuery、QSqlTableModel等のクラスにアクセスして、データベース操作を効率的に行うことができる。<br> <br> このモジュールは、SQLite、MySQL、PostgreSQL、Oracle、SQL Server等、多くのデータベースシステムをサポートしており、<br> 使用するデータベースに応じて、適切なドライバーを選択する必要がある。<br> <br><br> == MariaDB == 以下の例では、MariaDBのデータベースを使用して、以下に示すようなテーブルを作成して基本的なCRUD操作を行っている。<br> 実務では、必要に応じてフィールドを追加、または、データ型や制約を調整したりする必要がある。<br> * テーブル名 *: people * id *: INT型 *: 制約 1 : AUTO_INCREMENT *: 制約 2 : PRIMARY KEY *: 各レコードを一意に識別するための自動増分の主キー。 * name *: VARCHAR(40)型 *: 制約 : NOT NULL *: 名前を格納するフィールドで、最大40文字まで保存可能。 * age *: INT型 *: 年齢を格納する整数型のフィールド。 <br> <u>また、使用時にはエラーハンドリングおよびセキュリティ対策 (SQLインジェクション対策等) を適切に実装することを推奨する。</u><br> * ロギング機能の追加 * リトライメカニズムの実装 (一時的なネットワーク問題などに対処するため) * 詳細なエラータイプの定義 (例:接続エラー、クエリエラー等) * パラメータのバリデーション * SQLインジェクション対策の強化 <br> 開発向けMariaDBライブラリをインストールする。<br> # RHEL sudo dnf install mariadb-devel # SUSE sudo zypper install libmariadbd-devel <br> <syntaxhighlight lang="cmake"> # CMakeLists.txtファイル cmake_minimum_required(VERSION 3.21) project(QtMariaDBProject LANGUAGES CXX) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Sql) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Sql) # MariaDB Connector/Cを検索 find_path(MARIADB_INCLUDE_DIR mysql.h /usr/include/mysql ) find_library(MARIADB_LIBRARY NAMES mariadb PATHS /usr/lib /usr/lib64 ) if(NOT MARIADB_INCLUDE_DIR OR NOT MARIADB_LIBRARY) message(FATAL_ERROR "MariaDB Connector/C not found!") endif() add_executable(QtMariaDBProject main.cpp DataBaseManager.h DataBaseManager.cpp ) # QtライブラリとMariaDBライブラリをリンク target_link_libraries(QtMariaDBProject PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Sql ${MARIADB_LIBRARY} ) # MariaDBのヘッダファイルのディレクトリを追加 target_include_directories(QtMariaDBProject PRIVATE ${MARIADB_INCLUDE_DIR} ) </syntaxhighlight> <br> <syntaxhighlight lang="c++"> // DataBaseManager.hファイル #include <QtSql> #include <QString> #include <QSqlError> #include <stdexcept> #include <QDebug> class DatabaseException : public std::runtime_error { public: DatabaseException(const QString& message) : std::runtime_error(message.toStdString()) {} }; class DatabaseManager { public: DatabaseManager(); ~DatabaseManager(); bool openConnection(); void closeConnection(); bool createTable(); bool insertRecord(const QString &name, int age); bool updateRecord(int id, const QString &name, int age); bool deleteRecord(int id); QList<QMap<QString, QVariant>> readAllRecords(); void beginTransaction(); void commitTransaction(); void rollbackTransaction(); // 複数の操作をトランザクションで実行する場合のメソッド void performComplexOperation(const QString &name1, int age1, const QString &name2, int age2); private: QSqlDatabase db; void checkConnection(); void handleDatabaseError(const QString &operation, const QSqlError &error); }; </syntaxhighlight> <br> <syntaxhighlight lang="c++"> // DataBaseManager.cppファイル #include "DataBaseManager.h" DatabaseManager::DatabaseManager() { db = QSqlDatabase::addDatabase("QMYSQL"); db.setHostName("<ホスト名またはIPアドレス 例: localhost>"); db.setDatabaseName("<データベース名 例: sampledb>"); db.setUserName("<データベースのユーザ名>"); db.setPassword("<データベースのユーザ名のパスワード>"); } DatabaseManager::~DatabaseManager() { closeConnection(); } // データベースの接続 bool DatabaseManager::openConnection() { if (!db.open()) { throw DatabaseException("Failed to open database connection: " + db.lastError().text()); } qDebug() << "Database connection opened successfully"; } // データベースの切断 void DatabaseManager::closeConnection() { if (db.isOpen()) { db.close(); qDebug() << "Database connection closed"; } } // 接続の確認 void DatabaseManager::checkConnection() { if (!db.isOpen()) { throw DatabaseException("Database connection is not open"); } } // エラーハンドリング処理 void DatabaseManager::handleDatabaseError(const QString &operation, const QSqlError &error) { QString errorMessage = QString("%1 failed: %2").arg(operation, error.text()); throw DatabaseException(errorMessage); } // トランザクションを開始 void DatabaseManager::beginTransaction() { checkConnection(); if (!db.transaction()) { throw DatabaseException("Failed to start transaction: " + db.lastError().text()); } qDebug() << "Transaction started"; } // トランザクションをコミット void DatabaseManager::commitTransaction() { checkConnection(); if (!db.commit()) { throw DatabaseException("Failed to commit transaction: " + db.lastError().text()); } qDebug() << "Transaction committed"; } // トランザクションをロールバック void DatabaseManager::rollbackTransaction() { checkConnection(); if (!db.rollback()) { throw DatabaseException("Failed to rollback transaction: " + db.lastError().text()); } qDebug() << "Transaction rolled back"; } // 複数の操作を1つのトランザクションとして実行するメソッド void DatabaseManager::performComplexOperation(const QString &name1, int age1, const QString &name2, int age2) { try { beginTransaction(); insertRecord(name1, age1); insertRecord(name2, age2); commitTransaction(); qDebug() << "Complex operation completed successfully"; } catch (const DatabaseException& e) { rollbackTransaction(); throw DatabaseException("Complex operation failed: " + QString(e.what())); } } // テーブルの作成 bool DatabaseManager::createTable() { checkConnection(); QSqlQuery query; if (!query.exec("CREATE TABLE IF NOT EXISTS people (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(40) NOT NULL, age INT)")) { handleDatabaseError("Create table", query.lastError()); } qDebug() << "Table 'people' created or already exists"; } // 単一のレコードの追加 bool DatabaseManager::insertRecord(const QString& name, int age) { checkConnection(); QSqlQuery query; query.prepare("INSERT INTO people (name, age) VALUES (:name, :age)"); query.bindValue(":name", name); query.bindValue(":age", age); if (!query.exec()) { handleDatabaseError("Insert record", query.lastError()); } qDebug() << "Record inserted successfully"; } // 単一のレコードの更新 bool DatabaseManager::updateRecord(int id, const QString& name, int age) { checkConnection(); QSqlQuery query; query.prepare("UPDATE people SET name = :name, age = :age WHERE id = :id"); query.bindValue(":id", id); query.bindValue(":name", name); query.bindValue(":age", age); if (!query.exec()) { handleDatabaseError("Update record", query.lastError()); } if (query.numRowsAffected() == 0) { throw DatabaseException(QString("No record found with id: %1").arg(id)); } qDebug() << "Record updated successfully"; } // レコードの削除 bool DatabaseManager::deleteRecord(int id) { checkConnection(); QSqlQuery query; query.prepare("DELETE FROM people WHERE id = :id"); query.bindValue(":id", id); if (!query.exec()) { handleDatabaseError("Delete record", query.lastError()); } if (query.numRowsAffected() == 0) { throw DatabaseException(QString("No record found with id: %1").arg(id)); } qDebug() << "Record deleted successfully"; } // 全てのレコードを読み込む QList<QMap<QString, QVariant>> DatabaseManager::readAllRecords() { checkConnection(); QSqlQuery query("SELECT * FROM people"); QList<QMap<QString, QVariant>> results; if (!query.exec()) { handleDatabaseError("Read all records", query.lastError()); } while (query.next()) { QMap<QString, QVariant> record; record["id"] = query.value(0); record["name"] = query.value(1); record["age"] = query.value(2); results.append(record); } return results; } </syntaxhighlight> <br> <syntaxhighlight lang="c++"> // main.cppファイル int main() { DatabaseManager dbManager; try { // データーベースの接続 dbManager.openConnection(); // テーブルの作成 dbManager.createTable(); // トランザクションを使用した複雑な操作 dbManager.performComplexOperation("Alice", 28, "Bob", 32); // 個別のトランザクション管理の例 dbManager.beginTransaction(); try { // 既存のレコードの更新 dbManager.updateRecord(1, "John Doe Updated", 31); // 任意のレコードの削除 dbManager.deleteRecord(2); dbManager.commitTransaction(); } catch (const DatabaseException& e) { dbManager.rollbackTransaction(); qCritical() << "Transaction failed:" << e.what(); } // 全てのレコードを読み込む QList<QMap<QString, QVariant>> records = dbManager.readAllRecords(); for (const auto &record : records) { qDebug() << "ID:" << record["id"].toInt() << "Name:" << record["name"].toString() << "Age:" << record["age"].toInt(); } // 全てのレコードを読み込む records = dbManager.readAllRecords(); for (const auto& record : records) { qDebug() << "ID:" << record["id"].toInt() << "Name:" << record["name"].toString() << "Age:" << record["age"].toInt(); } } catch (const DatabaseException &e) { // データベース関連のエラー qCritical() << "Database error: " << e.what(); } catch (const std::exception &e) { // その他のエラー qCritical() << "Unexpected error: " << e.what(); } return 0; } </syntaxhighlight> <br> トランザクションを使用するメリットを以下に示す。<br> * データの一貫性 *: 複数の操作を1つの単位として扱うことができる。 * エラー回復 *: 問題が発生した場合、簡単に全ての変更を元に戻すことができる。 * パフォーマンス *: 多数の操作を一度のトランザクションで行うことにより、データベースとの通信回数を減らし、パフォーマンスを向上させることができる。 <br> ただし、トランザクション管理を使用する場合は、以下に示す事柄に注意すること。<br> * トランザクションは必要な場合にのみ使用して、不必要に長く保持しないようにする。 * ネストされたトランザクションの扱いには注意が必要である。<br><code>QSQLDatabase</code>クラスは、一般的にネストされたトランザクションをサポートしていない。 * 大規模なデータ操作を行う場合は、適切なチェックポイントを設定することを検討する。 <br><br> == SQLite3 == Qtを使用してSQLite3のテーブルにアクセスする場合、まず、<code>QSqlDatabase</code>クラスを使用してデータベースに接続する。<br> <syntaxhighlight lang="c++"> #include <QSqlDatabase> #include <QSqlQuery> // SQLiteデータベースに接続する QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); db.setDatabaseName("<SQLiteデータベース名>.sqlite"); // データベースファイル名 if (!db.open()) { qDebug() << "データベースに接続できませんでした。"; return; } </syntaxhighlight> <br> 次に、<code>QSqlQuery</code>クラスを使用してクエリを実行する。<br> 以下の例では、テーブルのデータを取得している。<br> <syntaxhighlight lang="c++"> QSqlQuery query; query.prepare("SELECT * FROM <SQLiteデータベースのテーブル名>"); if (query.exec()) { while (query.next()) { // レコードの処理 QString column1 = query.value(0).toString(); // 1番目の列 QString column2 = query.value(1).toString(); // 2番目の列 // 他の列も同様に取得できる } } else { qDebug() << "クエリの実行に失敗しました."; } // データベース接続を閉じる db.close(); </syntaxhighlight> <br><br> == SQLインジェクション対策 == SQLインジェクション対策では、プレースホルダを使用してクエリを構築することが重要である。<br> <br> 以下の例では、":username"がプレースホルダとなり、ユーザからの入力等が直接クエリに組み込まれることなく、安全にクエリが実行される。<br> また、ユーザからの入力をクエリに組み込む場合、入力データを適切にサニタイズしてクエリに含めるようにすることにより、悪意のあるSQLコードが挿入されても実行されないようにする。<br> <syntaxhighlight lang="c++"> QSqlQuery query; QString username = "user_input"; // ユーザからの入力等 // プレースホルダを使用して安全にクエリを構築 query.prepare("SELECT * FROM users WHERE username = :username"); query.bindValue(":username", username); if (query.exec()) { while (query.next()) { // レコードの処理 // ...略 } } else { qDebug() << "クエリの実行に失敗しました."; } </syntaxhighlight> <br><br> __FORCETOC__ [[カテゴリ:Qt]]
Qtの基礎 - データベース
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse