Room エンティティを使用してデータを定義する

Room 永続ライブラリを使用する場合、関連するフィールドのセットをエンティティとして定義します。エンティティごとに、関連付けられた Database オブジェクト内にテーブルが作成され、アイテムが格納されます。エンティティ クラスは、Database クラス内の entities 配列で参照する必要があります。

エンティティを定義する方法を次のコード スニペットに示します。

Kotlin

    @Entity
    data class User(
        @PrimaryKey var id: Int,
        var firstName: String?,
        var lastName: String?
    )
    

Java

    @Entity
    public class User {
        @PrimaryKey
        public int id;

        public String firstName;
        public String lastName;
    }
    

フィールドを永続化するには、Room がそのフィールドにアクセスできる必要があります。フィールドを公開したり、そのゲッターやセッターを指定したりすることができます。getter メソッドや setter メソッドを使用する場合は、Room の JavaBeans 規則に基づきます。

主キーを使用する

各エンティティは、少なくとも 1 つのフィールドを主キーとして定義する必要があります。フィールドが 1 つしかない場合でも、そのフィールドに @PrimaryKey アノテーションを付ける必要があります。また、Room によって自動 ID をエンティティに割り当てる場合は、@PrimaryKeyautoGenerate プロパティを設定します。エンティティが複合主キーを持つ場合は、@Entity アノテーションの primaryKeys プロパティを使用します。次のコード スニペットをご覧ください。

Kotlin

    @Entity(primaryKeys = arrayOf("firstName", "lastName"))
    data class User(
        val firstName: String?,
        val lastName: String?
    )
    

Java

    @Entity(primaryKeys = {"firstName", "lastName"})
    public class User {
        public String firstName;
        public String lastName;
    }
    

デフォルトでは、Room はクラス名をデータベース テーブル名として使用します。テーブルに別の名前を付ける場合は、@Entity アノテーションの tableName プロパティを設定します。次のコード スニペットをご覧ください。

Kotlin

    @Entity(tableName = "users")
    data class User (
        // ...
    )
    

Java

    @Entity(tableName = "users")
    public class User {
        // ...
    }
    

注: SQLite のテーブル名では、大文字と小文字が区別されません。

tableName プロパティと同様、Room はフィールド名をデータベースの列名として使用します。列に別の名前を付ける場合は、@ColumnInfo アノテーションをフィールドに追加します。次のコード スニペットをご覧ください。

Kotlin

    @Entity(tableName = "users")
    data class User (
        @PrimaryKey val id: Int,
        @ColumnInfo(name = "first_name") val firstName: String?,
        @ColumnInfo(name = "last_name") val lastName: String?
    )
    

Java

    @Entity(tableName = "users")
    public class User {
        @PrimaryKey
        public int id;

        @ColumnInfo(name = "first_name")
        public String firstName;

        @ColumnInfo(name = "last_name")
        public String lastName;
    }
    

フィールドを無視する

デフォルトでは、Room はエンティティ内で定義されているフィールドごとに列を作成します。 エンティティ内に永続化しないフィールドがある場合は、@Ignore を使用して対象フィールドにアノテーションを付けます。次のコード スニペットをご覧ください。

Kotlin

    @Entity
    data class User(
        @PrimaryKey val id: Int,
        val firstName: String?,
        val lastName: String?,
        @Ignore val picture: Bitmap?
    )
    

Java

    @Entity
    public class User {
        @PrimaryKey
        public int id;

        public String firstName;
        public String lastName;

        @Ignore
        Bitmap picture;
    }
    

エンティティが親エンティティからフィールドを継承している場合、通常は @Entity 属性の ignoredColumns プロパティを使用する方が簡単です。

Kotlin

    open class User {
        var picture: Bitmap? = null
    }

    @Entity(ignoredColumns = arrayOf("picture"))
    data class RemoteUser(
        @PrimaryKey val id: Int,
        val hasVpn: Boolean
    ) : User()
    

Java

    @Entity(ignoredColumns = "picture")
    public class RemoteUser extends User {
        @PrimaryKey
        public int id;

        public boolean hasVpn;
    }
    

Room は、データベースのテーブル内の詳細情報を簡単に検索できるように、さまざまなタイプのアノテーションをサポートしています。アプリの minSdkVersion が 16 未満でなければ、全文検索を利用できます。

全文検索をサポートする

全文検索(FTS)を通じてデータベース情報に迅速にアクセスする必要があるアプリの場合、FTS3 または FTS4 の SQLite 拡張モジュールを使用した仮想テーブルで、エンティティをバックアップします。Room 2.1.0 以降で利用可能なこの機能を使用するには、対象エンティティに @Fts3 または @Fts4 のアノテーションを追加します。次のコード スニペットをご覧ください。

Kotlin

    // Use `@Fts3` only if your app has strict disk space requirements or if you
    // require compatibility with an older SQLite version.
    @Fts4
    @Entity(tableName = "users")
    data class User(
        /* Specifying a primary key for an FTS-table-backed entity is optional, but
           if you include one, it must use this type and column name. */
        @PrimaryKey @ColumnInfo(name = "rowid") val id: Int,
        @ColumnInfo(name = "first_name") val firstName: String?
    )
    

Java

    // Use `@Fts3` only if your app has strict disk space requirements or if you
    // require compatibility with an older SQLite version.
    @Fts4
    @Entity(tableName = "users")
    public class User {
        // Specifying a primary key for an FTS-table-backed entity is optional, but
        // if you include one, it must use this type and column name.
        @PrimaryKey
        @ColumnInfo(name = "rowid")
        public int id;

        @ColumnInfo(name = "first_name")
        public String firstName;
    }
    

テーブルが複数の言語のコンテンツをサポートしている場合は、languageId オプションを使用して、各行の言語情報を格納する列を指定します。

Kotlin

    @Fts4(languageId = "lid")
    @Entity(tableName = "users")
    data class User(
        // ...
        @ColumnInfo(name = "lid") val languageId: Int
    )
    

Java

    @Fts4(languageId = "lid")
    @Entity(tableName = "users")
    public class User {
        // ...

        @ColumnInfo(name = "lid")
        int languageId;
    }
    

Room には、結果の順序化や、トークナイザー型、外部コンテンツとして管理されるテーブルなど、FTS バックアップ型エンティティを定義するためのオプションが幅広く用意されています。各オプションの詳細については、FtsOptions リファレンスをご覧ください。

特定の列をインデックスに登録する

FTS3 / FTS4 テーブル バックアップ型エンティティを使用できない SDK バージョンをサポートする必要があるアプリの場合は、データベース内の特定の列をインデックスに登録することで、クエリを高速化できます。エンティティにインデックスを追加するには、@Entity アノテーション内に indices プロパティを追加して、インデックスまたは複合インデックスに登録する列の名前をリストアップします。このアノテーション プロセスを実行するコード スニペットを以下に示します。

Kotlin

    @Entity(indices = arrayOf(Index(value = ["last_name", "address"])))
    data class User(
        @PrimaryKey val id: Int,
        val firstName: String?,
        val address: String?,
        @ColumnInfo(name = "last_name") val lastName: String?,
        @Ignore val picture: Bitmap?
    )
    

Java

    @Entity(indices = {@Index("name"),
            @Index(value = {"last_name", "address"})})
    public class User {
        @PrimaryKey
        public int id;

        public String firstName;
        public String address;

        @ColumnInfo(name = "last_name")
        public String lastName;

        @Ignore
        Bitmap picture;
    }
    

データベース内の特定のフィールドやフィールド グループを一意にすることが必要となる場合があります。 この一意性プロパティを適用するには、@Index アノテーションの unique プロパティを true に設定します。firstName 列と lastName 列に対して同一の値セットを持つ 2 つの行がテーブル内に存在しないようにする例を次のサンプルコードに示します。

Kotlin

    @Entity(indices = arrayOf(Index(value = ["first_name", "last_name"],
            unique = true)))
    data class User(
        @PrimaryKey val id: Int,
        @ColumnInfo(name = "first_name") val firstName: String?,
        @ColumnInfo(name = "last_name") val lastName: String?,
        @Ignore var picture: Bitmap?
    )
    

Java

    @Entity(indices = {@Index(value = {"first_name", "last_name"},
            unique = true)})
    public class User {
        @PrimaryKey
        public int id;

        @ColumnInfo(name = "first_name")
        public String firstName;

        @ColumnInfo(name = "last_name")
        public String lastName;

        @Ignore
        Bitmap picture;
    }
    

AutoValue ベースのオブジェクトを含める

Room 2.1.0 以降では、@AutoValue を使用してアノテーションを付けることで、Java ベースの不変値クラスを、アプリのデータベース内のエンティティとして使用できます。この機能は特に、「エンティティの 2 つのインスタンスに関して、列に同じ値が格納されている場合は等しいと見なす」というケースで役立ちます。

@AutoValue アノテーションの付いたクラスをエンティティとして使用する場合、@PrimaryKey@ColumnInfo@Embedded@Relation を使用してクラスの抽象メソッドにアノテーションを付けることができます。ただし、このようなアノテーションを使用する場合は、メソッドの自動生成実装を Room が適切に解釈できるように、毎回 @CopyAnnotations アノテーションを含める必要があります。

Room がエンティティとして認識できる @AutoValue アノテーション付きクラスの例を次のコード スニペットに示します。

User.java

    @AutoValue
    @Entity
    public abstract class User {
        // Supported annotations must include `@CopyAnnotations`.
        @CopyAnnotations
        @PrimaryKey
        public abstract long getId();

        public abstract String getFirstName();
        public abstract String getLastName();

        // Room uses this factory method to create User objects.
        public static User create(long id, String firstName, String lastName) {
            return new AutoValue_User(id, firstName, lastName);
        }
    }