Room使ってみた

Room Persistence Library 使ってみた。

Room Persistence Libraryとはなんぞ

The Room persistence library provides an abstraction layer over SQLite to allow fluent database access while harnessing the full power of SQLite.

https://developer.android.com/topic/libraries/architecture/room

とある。Androidのデータベースアクセスを抽象化したライブラリーっぽい。個人的にはかなり抽象化されているので作らなきゃいけないものも少し多いなっていうイメージだった。

データベースのテストを書く

今回はEntityとして、名前とid(自動インクリメント)を持つEntityをかいてみた。テストの時はinMemoryのデータベースを書いた方がいいらしい。

import android.arch.persistence.room.Room;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertThat;

@RunWith(AndroidJUnit4.class)
public class SimpleEntityTest {
    private EntryDao mEntryDao;
    private AppDatabase mDb;

    @Before
    public void createDb() {
        Context context = InstrumentationRegistry.getTargetContext();
        mDb = Room.inMemoryDatabaseBuilder(context,AppDatabase.class).build();
        mEntryDao = mDb.entryDao();
    }

    @After
    public void closeDb(){
        mDb.close();
    }

    @Test
    public void writeAndReadOneEntry(){
        Entry entry = new Entry();
        entry.setName("Test1");
        mEntryDao.insertAll(entry);
        Entry gotEntry = mEntryDao.getEntryByName("Test1");
        assertThat(gotEntry,equalTo(entry));

    }
}

Entity

EntryっていうEntityを書いた。

import android.arch.persistence.room.ColumnInfo;
import android.arch.persistence.room.Entity;
import android.arch.persistence.room.PrimaryKey;

import java.util.Objects;


@Entity(tableName = "entries")
public class Entry {

    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "entry_id")
    private long eid;

    @ColumnInfo(name = "name")
    private String name;


    public void setName(String name) {
        this.name = name;
    }

    public long getEid() {
        return eid;
    }

    public void setEid(long eid) {
        this.eid = eid;
    }

    public String getName() {
        return name;
    }
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Entry entry = (Entry) o;
        return Objects.equals(name, entry.name);
    }

    @Override
    public int hashCode() {

        return Objects.hash(eid, name);
    }
}

equalsをOverrideしないとTestのequalToで等しくならないので、nameだけ同じなら同じってことにした。primary keyのautoGenerate=trueでオートインクリメントできるらしい。

Dao

DaoはEntityのインターフェースとなる部分。ここに動作を書く。

import android.arch.persistence.room.Dao;
import android.arch.persistence.room.Delete;
import android.arch.persistence.room.Insert;
import android.arch.persistence.room.Query;

import java.util.List;

@Dao
public interface EntryDao {
    @Query("SELECT * FROM entries")
    List<Entry> getAll();

    @Query("SELECT * FROM entries WHERE name LIKE :name LIMIT 1")
    Entry getEntryByName(String name);

    @Insert
    void insertAll(Entry... entries);

    @Delete
    void delete(Entry entry);
}

DaoアノテーションでDaoであることを示す。Queryアノテーションで実行するQueryを指定する。

Database

import android.arch.persistence.room.Database;
import android.arch.persistence.room.RoomDatabase;

@Database(entities = {Entry.class},version = 1)
public abstract class AppDatabase extends RoomDatabase {
    public abstract EntryDao entryDao();
}

データベース。RoomDatabaseを継承したものをつくる。

テストの実行

これでテストはパスした。
エンティティにDateの属性を付けようとしていろいろ調べたけど、jack(java android compiler kit)の警告が出たりして、時間がたりなかったのでやめた。utilのDate使うよりOffsetDateTime(jave8)を使うのがいいらしい。Dateはタイムゾーンを考慮しないので。でも、OffsetDateTimeを入れるとjackとソースコンパティビリティの警告出るんだよなぁ。build.gradleでjack enabled=trueを入れてcompileOptionを消せばいいんだけどなんだかなぁという感じだった(加藤恵)。あとでちゃんとやってみたい。

その他

python書きてぇなつってjavaandroid書いてる。kivyとpySerialでpic18f14k50でシリアル通信するデスクトップアプリ書こうかなって隙間時間はkivy調べてる。さっさとandroid書き終わりたいなぁ。ぜんぜんhackしてないけど許してにゃん。