[コラム]データベース操作に関するcore処理について

データベース(SQLite3)操作に関する「core」処理は、データベースとの直接的なやり取りの担当側が、query等の基本レベルメソッドを基にして、作成される低レベルな関数やメソッドを指します。
これらはデータベースエンジンに対する直接的なクエリの実行やトランザクションの管理を行い、アプリケーションの他の部分では抽象化された形で扱われる様に作成します。
以下に、一般的なデータベース操作で作成・使用される「core」処理をいくつか紹介します。

1.CRUD操作

基本的なデータ操作で、Create(作成)、Read(読み取り)、Update(更新)、Delete(削除)を含みます。

(1) coreInsert

データをデータベースに挿入します。通常は新しいレコードの追加に使われます。

Future<int> coreInsert(String table, Map<String, dynamic> data);

(2) coreSelect

特定の条件に基づいてデータを検索・抽出します。

Future<List<Map<String, dynamic>>> coreSelect(String table, {String? where, List<dynamic>? whereArgs});

(3) coreUpdate

指定された条件に基づいてデータを更新します。

Future<int> coreUpdate(String table, Map<String, dynamic> data, {String? where, List<dynamic>? whereArgs});

(4) coreDelete

特定の条件でデータを削除します。

Future<int> coreDelete(String table, {String? where, List<dynamic>? whereArgs});

2.トランザクション管理

データの整合性を保つために重要な操作で、複数の処理を一つの作業単位として扱います。

(1) coreBeginTransaction

新しいトランザクションを開始します。

Future<void> coreBeginTransaction();

(2) coreCommit

トランザクションをコミットし、変更をデータベースに永続化します。

Future<void> coreCommit();

(3) coreRollback

トランザクション中のすべての変更を取り消します。

Future<void> coreRollback();

3.スキーマ管理

データベースの構造を定義または変更する操作です。

(1) coreCreateTable

新しいテーブルを作成します。

Future<void> coreCreateTable(String sql);

(2) coreAlterTable

既存のテーブル構造を変更します。

Future<void> coreAlterTable(String sql);

(3) coreDropTable

Future<void> coreAlterTable(String sql);

(4) coreDropTable

テーブルを削除します。

Future<void> coreDropTable(String tableName);

これらのメソッドは、データベースと直接対話するための基本的な構成要素を提供し、アプリケーションの他の部分からは抽象化された形でアクセスされることが一般的です。

4.実装例

以下は、CRUD操作、トランザクション管理、スキーマ管理を含む拡張された DBHelper クラスの完全な実装例です。
これは、SQLiteデータベースを扱うための一般的なユーティリティクラスとして設計されており、Dart(Flutter)アプリケーションでのデータベース操作を抽象化し、様々なデータベースタスクを容易にします。

DBHelper:
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';

class DBHelper {
  Database? _database;

  static final DBHelper _instance = DBHelper._internal();
  factory DBHelper() => _instance;

  DBHelper._internal();

  // データベースへの参照を取得または作成
  Future<Database> get database async {
    if (_database != null) return _database!;
    _database = await _initDatabase();
    return _database!;
  }

  // データベースの初期化
  Future<Database> _initDatabase() async {
    String path = join(await getDatabasesPath(), 'app_database.db');
    return await openDatabase(
      path,
      version: 1,
      onCreate: (Database db, int version) async {
        // 初期テーブル作成
        await db.execute(
          "CREATE TABLE tasks (id INTEGER PRIMARY KEY AUTOINCREMENT, task TEXT)",
        );
      },
    );
  }

  // CRUD操作
  Future<int> coreInsert(String table, Map<String, dynamic> data) async {
    final db = await database;
    return await db.insert(table, data);
  }

  Future<List<Map<String, dynamic>>> coreSelect(String table, {String? where, List<dynamic>? whereArgs}) async {
    final db = await database;
    return await db.query(table, where: where, whereArgs: whereArgs);
  }

  Future<int> coreUpdate(String table, Map<String, dynamic> data, {String? where, List<dynamic>? whereArgs}) async {
    final db = await database;
    return await db.update(table, data, where: where, whereArgs: whereArgs);
  }

  Future<int> coreDelete(String table, {String? where, List<dynamic>? whereArgs}) async {
    final db = await database;
    return await db.delete(table, where: where, whereArgs: whereArgs);
  }

  // トランザクション管理
  Future<void> coreBeginTransaction() async {
    final db = await database;
    await db.transaction((txn) async {
      // トランザクションの開始
    });
  }

  Future<void> coreCommit() async {
    // トランザクションのコミット
  }

  Future<void> coreRollback() async {
    // トランザクションのロールバック
  }

  // スキーマ管理
  Future<void> coreCreateTable(String sql) async {
    final db = await database;
    await db.execute(sql);
  }

  Future<void> coreAlterTable(String sql) async {
    final db = await database;
    await db.execute(sql);
  }

  Future<void> coreDropTable(String tableName) async {
    final db = await database;
    await db.execute('DROP TABLE IF EXISTS $tableName');
  }
}

このクラスは、データベースの初期化、CRUD操作、トランザクションの管理、そしてテーブルの作成、変更、削除を行うメソッドを提供します。このように実装することで、アプリケーション全体でデータベース操作が一元管理され、保守性や再利用性が向上します。また、このクラスはシングルトンパターンを採用しているため、アプリケーション全体で一つのインスタンスのみが使用されます。

5.ただし書き

上記のDBHelperクラスはSQLiteデータベースを操作するために設計されていますが、実装例にはFlutterの環境でよく使われるsqfliteパッケージを利用しています。sqfliteはFlutterでSQLiteデータベースを操作するための標準的なライブラリであり、Dartの非同期機能をフルに活用しています。

ただし、sqfliteはFlutterのモバイルプラットフォーム(AndroidとiOS)での使用に限られています。もし、デスクトップアプリケーション(Windows, macOS, Linux)やウェブアプリケーションでSQLiteを利用したい場合は、それぞれに適した別のライブラリを使用する必要があります。例えば、FlutterのデスクトップアプリでSQLiteを使用するにはsqflite_common_ffi を利用することが一般的です。

sqfliteを使った上記のコードは、AndroidとiOSデバイス上でのデータベース操作を容易にし、CRUD操作やトランザクション、スキーマの管理を行うための堅牢な基盤を提供します。各関数は非同期で動作し、Flutterの非同期処理モデルに適合しているため、UIのブロックを防ぎつつデータベース操作が可能です。

コメントを残す