以前ちらっと書いた、モデル中心の設計をするために、最近は本業のほうでも趣味の方でも、 realm-java をヘビーユースしています。
まえおき: Realmって関連モデル扱うとき本当に便利だよ!
SQLだと、 User has_many Message みたいなのを扱うとき、ちょいちょい面倒だったんですが、Realmだと
class User extends RealmObject {
@PrimaryKey
private long id;
private String name;
}
class Message extends RealmObject {
@PrimaryKey
private long id;
private String body;
private User sender;
}
みたいなモデルを定義しておけば
messages = [
{
id: 12,
body: "お元気ですか",
sender: {
id: 1
}
},
{
id: 11,
body: "こんにちは",
sender: {
id: 1
}
}
]
users = [
{
id: 1,
name: "山田太郎"
},
{
id: 2,
name: "岩木祐輔"
}
]
みたいなJSONを
JSONArray users = ... ; //上記のJSON
JSONArray messages = ... ; // 〃
Realm.getDefaultInstance().executeTransaction(new RealmTransaction(
public void execute(Realm realm) {
realm.createOrUpdateAllFromJson(User.class, users);
realm.createOrUpdateAllFromJson(Message.class, message);
}
));
ってかんじで関連をそのまま突っ込めるし、取得の時もいちいちJOINとか考えずに
Realm.getDefaultInstance().where(Message.class).equalsTo("sender.id", 2).findAll();
で id=2(岩木祐輔) さんのメッセージを取れるし、めっちゃ便利〜♪ なんです。
まえおき2: Realmは使い終わったらclose()を呼ばないとイケナイ
データベースなんで当たり前といえば当たり前なんですが、使い終わったらお掃除をちゃんとしないと、リソースリークするようです。
とはいえ・・・ close
って忘れがちですよね。
というか、そもそも RealmTransactionなんていう素晴らしい仕組みがあるんだったら、Transaction抜けたらDBもcloseしてよー って思いません?(言い過ぎw
以前、SQLiteOpenHelper を使うときには、getReadableDatabase/getWritableDatabaseを直接使わない! っていう煽りっぽい記事かいたときにもちらっと書いてたんですが、個人的には、DBを使うスコープはPythonのwith構文みたいに明示的にスコープであって欲しい(open/close なんていちいち呼びたくない) という衝動から、すごく雑ですが、ライブラリを作るに至りました。
本題: realm-java-helpers。これでもう close忘れは起こさない
DBからReadするとき
RealmHelper.executeTransactionForRead(new RealmTransaction() {
public void execute(Realm realm) {
List<Message> messages = realm.where(Message.class).equalsTo("sender.id", 2).findAll();
/*
... messagesを使っていろいろ ...
*/
}
}); // このRealmTransactionを抜けたら勝手にRealm#closeされるので、リソースリークはしない
DBにWriteするとき
RealmHelper.rxExecuteTransactionAsync(new RealmTransaction() {
public void execute(Realm realm) {
/*
... realm にいろいろ書く ...
*/
}
}).subscribe(new Action1<Void>(){
public void call(Void xx) {
Log.d(TAG, "Successfully saved!");
}
}) // このsubscriptionを抜けたら勝手にRealm#closeされるので、リソースリークはしない
みたいな感じです。
未解決なところ
realm-android-adapters と組むときに、うまくScopedな感じでAdapterが使えるようにはなっていない。
ActivityとかFragmentみたいなライフサイクルをもった子たちに、イイカンジにRealmスコープをインジェクションできる仕組みってないかなぁ・・・ないよなぁ・・・ ということで、未解決です。
realm-java-helpers ぜひ使ってフィードバックください!
気になる点などは GitHub issueでおねがいします!