[基礎知識]ObjectBoxによるDB操作

ObjectBoxパッケージは、高速なオブジェクトデータベースを扱い、スキーママイグレーションが容易で、非常にパフォーマンスに優れています。

ObjectBoxパッケージの特徴:

メリット:

(1) 非常に高速:

  • ObjectBoxは、他の多くのデータベースソリューションと比較して非常に高速です。ネイティブコードを使用しており、特にモバイルアプリケーションにおいてパフォーマンスが優れています。

(2) 型安全:

  • Dart言語の型システムと統合されており、型安全なデータ操作が可能です。

(3) リアクティブプログラミングのサポート:

  • リアクティブなデータストリームを提供し、データの変更をリアルタイムで監視することができます。

(4) シンプルなAPI:

  • APIがシンプルで直感的です。データベース操作のための学習曲線が緩やかです。

(5) リレーショナルデータのサポート:

  • リレーショナルデータベースの特性を活かし、複雑なリレーションやクエリを簡単に管理できます。

(6) クロスプラットフォーム:

  • Android、iOS、Windows、macOS、Linuxなど、様々なプラットフォームで動作します。

デメリット:

(1) 依存関係の増加:

  • ObjectBoxを使用するためには、objectbox_flutter_libsobjectbox_generator などの依存関係が必要となり、プロジェクトの複雑さが増します。

(2) 学習曲線:

  • 高機能であるため、学習曲線がやや急です。特に、FlutterやDartに不慣れな初心者には難しい場合があります。

(3) パッケージサイズ:

  • ObjectBoxのパッケージサイズは他のデータベースソリューションと比較して大きい場合があります。

(4) コミュニティとサポート:

  • 他のデータベースソリューションと比べると、コミュニティとオンラインのサポートが少ない場合があります。

上記のうち、特に着目するべきなのは、リアクティブプログラミングです。
これは、データの変更をリアルタイムで監視し、それに応じてアプリケーションのUIや他の部分を自動的に更新するプログラミングパラダイムです。
これをサポートするデータベースは、データが変更されると自動的にその変更を検知し、関連するデータを再取得したり、UIを更新したりするための通知を提供します。

以下、ObjectBOXの利用手順です。(まずは基本的なDB操作のみの利用手順です)

ObjectBOXの利用手順:

1.Flutterプロジェクト作成

(1) ターミナルを開き、以下のコマンドを実行して新しいプロジェクトを作成します。

flutter create objectbox_example

(2) プロジェクトフォルダに移動します。

cd objectbox_example

2.必要なパッケージの追加

ObjectBoxを使用するために必要なパッケージ(次の4つ)を追加します。

objectbox と objectbox_flutter_libs は、アプリ実行時に使用されます。
故に、pubspec.yaml では、dependencies 句に登録します。

しかし、build_runner と objectbox_generator は、開発段階で使用します。
故に、pubspec.yaml では、dev_dependencies 句に登録します。

https://pub.dev/packages/objectbox/install
https://pub.dev/packages/objectbox_flutter_libs/install
https://pub.dev/packages/build_runner/install
https://pub.dev/packages/objectbox_generator/install

2.1 アプリ実行時に必要な(objectbox、objectbox_flutter_libs)パッケージの追加

(1) プロジェクトフォルダで次のコマンドによりobjectbox、objectbox_flutter_libs の各パッケージ(の依存関係)を追加します。

flutter pub add objectbox
flutter pub add objectbox_flutter_libs

(2) 次のコマンドで上記追加を反映します。

flutter pub get

(3) pubspec.yaml ファイルを開き、上記パッケージ(の依存関係)が追加されていることを確認します。

dependencies:
  flutter:
    sdk: flutter

  objectbox: ^4.0.1
  objectbox_flutter_libs: ^4.0.1

2.2 開発時に必要な(build_runner、objectbox_generator)パッケージの追加

(1) pubspec.yaml ファイルを開き、上記パッケージ(の依存関係)を追加します。

dev_dependencies:
  flutter_test:
    sdk: flutter

  build_runner: ^2.4.11
  objectbox_generator: ^4.0.1

(2) ターミナルで以下のコマンドを実行してパッケージをインストール(反映)します。

flutter pub get

3.ObjectBoxデータベースの設定と使用

ObjectBox の利用時には、DBを扱う為の、次の2つのファイルを作成する必要があります。

① データモデル(エンティティ)定義ファイル
② データベース操作の為のユーティリティクラス定義ファイル

概要:
① データモデル(エンティティ)定義ファイル:
  DBに保存されるオブジェクト構造を定義します。

② DB操作ユーティリティクラス定義ファイル:
  DB初期化、エンティティボックス取得、リアクティブクエリ設定などのロジックを含みます。

https://github.com/objectbox/objectbox-dart/commit/aceaa52f62a79a776573d3a3b3a9e30405016615

以下は、ObjectBoxデータベースを設定し、使用するためのサンプルコードです。

3.1 モデル(エンティティ)定義:

まず、データモデルを定義します。

(1) lib フォルダ内に models.dart ファイルを作成します。

(2) models.dart の内容:

import 'package:objectbox/objectbox.dart';

@Entity() // ObjectBoxのエンティティとして定義
class Item {
  @Id(assignable: true)
  int id;
  String name;

  Item({this.id = 0, required this.name});
}

3.2 DB操作定義:

3.2.1 DB操作定義(変換前)

次に、DB操作を定義します。

(1) lib フォルダ内に objectbox.dart ファイルを作成します。

(2) objectbox.dart の内容:

import 'models.dart';
import 'objectbox.g.dart'; // 自動生成されるファイルをインポート

class ObjectBox {
  late final Store store;
  late final Box<Item> itemBox;

  ObjectBox._create(this.store) {
    itemBox = Box<Item>(store);
  }

  /// Create an ObjectBox store
  static Future<ObjectBox> create() async {
    final store = await openStore();
    return ObjectBox._create(store);
  }
}

3.2.2 DB操作定義(変換後)-TypeAdapterの生成-

次に、上記object.dartを基にして、ObjectBoxのコード生成機能を使用してTypeAdapterを生成します。

(1) ターミナルで以下のコマンドを実行してTypeAdapterを生成します。

flutter pub run build_runner build

3.3 サンプルアプリの作成

次に、サンプルアプリを作成してObjectBoxデータベースを利用します。

(1) lib/main.dart ファイルを開き、以下のコードを追加します。

(2) main.dart の内容:

import 'package:flutter/material.dart';

import 'models.dart';
import 'objectbox.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized(); // Flutterバインディングの初期化
  final objectbox = await ObjectBox.create(); // ObjectBoxの初期化
  runApp(MyApp(objectbox: objectbox));
}

// メインアプリケーションクラス
class MyApp extends StatelessWidget {
  final ObjectBox objectbox;
  const MyApp({super.key, required this.objectbox});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'ObjectBox Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(objectbox: objectbox),
    );
  }
}

// ホーム画面クラス
class MyHomePage extends StatefulWidget {
  final ObjectBox objectbox;
  const MyHomePage({super.key, required this.objectbox});

  @override
  MyHomePageState createState() => MyHomePageState();
}

// ホーム画面の状態を管理するクラス
class MyHomePageState extends State<MyHomePage> {
  final TextEditingController _controller = TextEditingController(); // テキストフィールドのコントローラ
  List<Item> _items = []; // 取得したアイテムを格納するリスト

  @override
  void initState() {
    super.initState();
    _loadItems(); // アイテムをロード
  }

  // データベースからアイテムを読み込むメソッド
  void _loadItems() {
    setState(() {
      _items = widget.objectbox.itemBox.getAll();
    });
  }

  // アイテムを追加するメソッド
  void _addItem(String name) {
    final newItem = Item(name: name); // 新しいアイテムを作成
    widget.objectbox.itemBox.put(newItem); // アイテムをデータベースに追加
    _controller.clear(); // テキストフィールドをクリア
    _loadItems(); // アイテムを再読み込み
  }

  // アイテムを削除するメソッド
  void _deleteItem(int id) {
    widget.objectbox.itemBox.remove(id); // 指定したIDのアイテムを削除
    _loadItems(); // アイテムを再読み込み
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('ObjectBox Example'),
      ),
      body: ListView(
        padding: const EdgeInsets.all(8.0),
        children: [
          TextField(
            controller: _controller,
            decoration: InputDecoration(
              labelText: 'Item Name',
              suffixIcon: IconButton(
                icon: const Icon(Icons.add),
                onPressed: () {
                  if (_controller.text.isNotEmpty) {
                    _addItem(_controller.text); // アイテムを追加
                  }
                },
              ),
            ),
          ),
          const SizedBox(height: 10),
          ..._items.map((item) => ListTile(
            title: Text(item.name), // アイテムの名前を表示
            trailing: IconButton(
              icon: const Icon(Icons.delete),
              onPressed: () {
                _deleteItem(item.id); // アイテムを削除
              },
            ),
          )),
        ],
      ),
    );
  }
}

3.4 動作確認

下の様に、Item Name(TextField)に入力し、+アイコン(IconButton)をクリックすると、その都度、入力データがSQLiteに登録され、その下の表示欄(ListTile)に表示されていきます。

4.まとめ

objectboxの利用手順は、
①パッケージ追加(アプリ実行時に必要な2つ(objectbox、objectbox_flutter_libs))
②パッケージ追加(開発時に必要な2つ(build_runner、objectbox_generator))
③データのモデル定義(例:models.dart)
④DB操作定義(例:objectbox.dart)
⑤コード生成機能によるTypeAdapter生成(例:objectbox.g.dart)
⓺サンプルコード作成(例:main.dart)
という順番で行います。

上記②~⑤を注意すれば、極めて容易に、DB操作を実現できます。

コメントを残す