‘SQLite’ タグのついている投稿

AndroidのORM、greenDAOを使ってみた

Androidで使えるORMとしてはormliteが有名ですが、より高速だという触れ込みのgreenDAOを使ってみました。バージョンは1.2です。
greenDAO – Android ORM for SQLite | greenDAO is a light & fast ORM solution that maps objects to SQLite databases.

greenDAOはSQLiteをDAO(Data Access Object)で扱うことができます。
ジェネレーターを使ってエンティティとDAOをあらかじめ自動生成することで、データベース定義のコードを書く手間から解放されます。

このスライドも参考になります。後半はパフォーマンスに関する話題です。

まずはExampleを触ってみます。このExampleは自分で一度試してみたほうが良さそうです。今後はDaoExampleGeneratorを編集して自分のプロジェクトに適用することになるので。

EclipseのFileメニューからImport->Existing Projects into Workspaceで
DaoExample
DaoExampleGenerator
を取り込みます。

de.greenrobot.daogenerator.gentest.ExampleDaoGeneratorを見ると、バージョン番号、書き出し先のパッケージ名、スキーマ定義、そして書き出し先の相対パスを指定するだけの内容になっていることがわかります。

実際に使うときはこのファイルを書き換えてスキーマ定義をしていきます。
新規に同じ内容のプロジェクトを作ってしまってもいいですが、毎回このDaoExampleGeneratorをインポートして名前変更するのが楽かと思います。

WS000031

ジェネレーターはJava Applicationとして実行します。

image

ExampleDaoGeneratorを実行するとコンソールにログが出ます。

1
2
3
4
5
6
7
8
9
10
11
12
13
greenDAO Generator
Copyright 2011-2012 Markus Junginger, greenrobot.de. Licensed under GPL V3.
This program comes with ABSOLUTELY NO WARRANTY
Processing schema version 3...
Written C:\Users\test\Documents\workspace\DaoExample\src-gen\de\greenrobot\daoexample\NoteDao.java
Written C:\Users\test\Documents\workspace\DaoExample\src-gen\de\greenrobot\daoexample\Note.java
Written C:\Users\test\Documents\workspace\DaoExample\src-gen\de\greenrobot\daoexample\CustomerDao.java
Written C:\Users\test\Documents\workspace\DaoExample\src-gen\de\greenrobot\daoexample\Customer.java
Written C:\Users\test\Documents\workspace\DaoExample\src-gen\de\greenrobot\daoexample\OrderDao.java
Written C:\Users\test\Documents\workspace\DaoExample\src-gen\de\greenrobot\daoexample\Order.java
Written C:\Users\test\Documents\workspace\DaoExample\src-gen\de\greenrobot\daoexample\DaoMaster.java
Written C:\Users\test\Documents\workspace\DaoExample\src-gen\de\greenrobot\daoexample\DaoSession.java
Processed 3 entities in 334ms

これで上記ファイルが生成されました。

ちなみにExampleでは不要ですが、対象プロジェクトのsrc-genフォルダはあらかじめ作っておく必要があるようです。

また、プロジェクトのプロパティから、Java Build Path→Sourceタブを開いて、Add Folderを実行、src-genを追加する必要があります。

libsフォルダも作成して、greenDAO.jarをコピー、Java Build Path→Librariesタブ→Add JARsでgreenDAO.jarを参照します。

全件読み込みはloadAllメソッドを使えばリストオブジェクトで取得できます。

1
List<Note> list = noteDao.loadAll();

Cursorを取得する場合はSQLiteDatabaseに対してqueryを実行することもできます。

1
cursor = db.query(noteDao.getTablename(), noteDao.getAllColumns(), null, null, null, null, orderBy);

書き込みはオブジェクトのインスタンスを作成してinsert、という仕組みです。

1
2
Note note = new Note(null, noteText, comment, new Date());
noteDao.insert(note);

insert系メソッドも、同時に複数追加できるinsertInTxや、insertもしくはupdateで、さらに複数実行のinsertOrReplaceInTxなどもあります。

必要なら生成されたDAOを拡張してメソッド追加すれば色々便利そうです。

この辺はJavaDoc参照です。

http://greendao-orm.com/javadoc/greendao/

複雑な検索はクエリービルダーを使います。

Queries | greenDAO – Android ORM for SQLite

1
2
3
4
List joes = userDao.queryBuilder()
.where(Properties.FirstName.eq("Joe"))
.orderAsc(Properties.LastName)
.list();

サブクエリも自分で書けるみたいなので、greenDAOの利用が制約にならないというのはいいですね。

あと、バージョン番号は指定できますが、マイグレーション処理については自分で書く必要があります。DaoMaster.OpenHelper(SQLiteOpenHelperの拡張)を拡張してonUpgradeを書くことになります。初期データを入れたい場合も同じようにonCreateをオーバーライドします。そもそもOpenHelperはabstractなので必ずサブクラスを作る必要があります。

OpenHelperとDevOpenHelperがありますが、DevOpenHelperはonUpgrade時にデータベースを一度ドロップする点が違います。リリースビルドではOpenHelperのサブクラスを使います。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
public class MyOpenHelper extends OpenHelper {
 
    private static final String DB_NAME = "clocks-db";
 
    private SQLiteDatabase db = null;
    private DaoMaster daoMaster = null;
    private DaoSession daoSession = null;
 
    public MyOpenHelper(Context context, CursorFactory factory) {
        super(context, DB_NAME, factory);
 
        // onCreate呼び出しのためにデータベース作成
        this.getDatabase();
    }
 
    @Override
    public void onCreate(SQLiteDatabase db) {
        super.onCreate(db);
 
        // ローカル変数としてセッションを作成する
        DaoMaster daoMaster = new DaoMaster(db);
        DaoSession daoSession = daoMaster.newSession();
        // 初期データ作成
        ClockSettingDao clockSettingDao = daoSession.getClockSettingDao();
        ClockSetting data = new ClockSetting(null, "", 0, 0);
        clockSettingDao.insert(data);
    }
 
    @Override
    public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {
    }
 
    public SQLiteDatabase getDatabase() {
        if (this.db == null) {
            this.db = this.getWritableDatabase();
        }
 
        return this.db;
    }
 
    public DaoMaster getDaoMaster() {
        if (this.daoMaster == null) {
            this.daoMaster = new DaoMaster(this.getDatabase());
        }
 
        return this.daoMaster;
    }
 
    public DaoSession getDaoSession() {
        if (this.daoSession == null) {
            this.daoSession = this.getDaoMaster().newSession();
        }
 
        return this.daoSession;
    }
 
}

セッションはアプリケーションスコープで持つことを推奨されています。

http://greendao-orm.com/documentation/how-to-get-started/#comment-45

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class MyApplication extends Application {
 
    private MyOpenHelper dbHelper;
 
    @Override
    public void onCreate() {
        super.onCreate();
 
        this.dbHelper = new MyOpenHelper(this, null);
    }
 
    public DaoSession getDaoSession() {
        return this.dbHelper.getDaoSession();
    }
 
}

ちなみにcloseは不要です。

SQLiteを使う場合の注意点 – 一歩ずつコツコツと

AndroidManifest.xmlのapplicationにMyApplicationへのクラスパスを指定します。

1
2
3
4
5
6
<application
    android:name="test.MyApplication"
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/TestTheme" >

呼び出しはこんな形で。

1
2
3
4
5
6
MyApplication app = (MyApplication) getApplication();
DaoSession daoSession = app.getDaoSession();
ClockSettingDao clockSettingDao = daoSession.getClockSettingDao();
 
ClockSetting data = clockSettingDao.queryBuilder()
        .orderAsc(Properties.Priority).limit(1).list().get(0);

使ってみた感想ですが、あまり癖がないので使いやすいと思います。せっかくジェネレートしてくれるなら、自分の処理を追加するための拡張クラスも作っておいてくれるとさらに便利なのですが。

最後に、一点気になる点は、生成されたファイルがCR+LF改行だったことです。Windows環境だからかな…