note63

事情

greenDaoを使ってみる

はじめに


ORMLiteより2〜4倍早いという噂のgreenDaoを触ってみました。 英語ダメ太郎なので自分で気になったドキュメントの内容をまとめようと思います。

環境


  • MacOS X 10.9
  • AndoridStudio 0.4.7
  • GradleAndroidプロジェクト

導入手順


まずは導入から、これやんないと始まんないですね。
greendDaoではORMLiteのようにテーブルクラスを手書きするのではなく、GreenDaoGeneratorというクラスを使ってクラスファイルやDAOクラスを生成します。
こうすれば事前にDAOをテーブルごとに最適化できたりする(と思う)のでこのへんが高速化の肝なのかもしれません。

まず、クラス生成用のモジュールを作成します。
以下のブログの説明が丁寧でわかりやすいです。

僕の環境の場合Generator実行時にClassNotFoundExceptionを吐かれてしまったので以下の内容をbuild.gradleに行を追加しました。

apply plugin: 'java'
apply plugin: 'application' # 追加

あと、生成先となるディレクトリのパスは/Usersから指定しました。
普通に~/から指定するとなぜかAndroidStudio.app/bin/~/というパスで生成されました。(なぞい)

ちなみにgradle taskで生成する方法もある。

使い方


まずDaoMaster.OpenHelperを継承したヘルパークラスを作ります。
このへんはORMLiteといっしょ。
とりあえずこんな感じで作ってみる。

public class MyHelper extends OpenHelper {

    private static final String DB_NAME = "my-db";
    private static MyHelper INSTANCE;
    private static DaoMaster DAO_MASTER;
    private static DaoSession DAO_SESSION;

    private MyHelper(Context context, CursorFactory factory) {
        super(context, DB_NAME, factory);

        DAO_MASTER = new DaoMaster(this.getWritableDatabase());
        DAO_SESSION = DAO_MASTER.newSession();
    }

    private MyHelper getInstatce(Context context) {
        if(INSTANCE == null)
            INSTANCE = new MyHelper(context, null);

        return INSTANCE;
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }

    public static DaoMaster master() {
        return DAO_MASTER;
    }

    public static DaoSession session() {
        return DAO_SESSION;
    }
}

セッションはメモリ食うから何個も作るのはやめとくようにとのことなのでシングルトンインスタンス生成時に一緒に作って保持しておく。

  • Session

    New sessions can be created quite quickly. However, each session allocates memory, typically an session “cache” for entities.

    セッションはすぐ作られます。しかし、メモリを消費します。特にエンティティのキャッシュによって消費されます。

同じクエリを発行したときにセッションは内部的にエンティティをキャッシュしてるらしく、複数のセッションを作ると個々のセッションがこのキャッシュを保持してしまうということなんだと思います。

とりあえずselect分相当のことをしようと思うとこんな感じ

DaoSession session = MyHelper.getInstance(context).session();
NoteDao dao = session.getNoteDao();
dao.loadByRowId(1);

// セッションから呼び出すこともできる
session.load(Note.class, 1);

Tips


  • テーブル(クラス)は必ずlongかLong型のpirimary keyを持たなければいけない(今後解消される予定)
  • 継承、実装はsetSuperclass(),implementsInterface()を使って指定できる
  • クラスの生成先は2つ指定できるdaoGenerator.generateAll(schema, "path to directory", "path to another directory");
  • 自前のコードをクラスに記述したいときにはスキーマに対してenableKeepSectionsByDefault()を使うかエンティティに対してsetHasKeepSections(true)を呼び出し、// KEEP [...]からKEEP [...] ENDの間にコードを記述する

Relationsに関しては複雑そうだったのでまた別の機会に