Daten mithilfe von Zimmerentitäten definieren

Wenn Sie die Persistenzbibliothek für Räume zum Speichern der Daten Ihrer Anwendung verwenden, definieren Sie Entitäten zur Darstellung der zu speichernden Objekte. Jede Entität entspricht einer Tabelle in der zugehörigen Raumdatenbank und jede Instanz einer Entität stellt eine Datenzeile in der entsprechenden Tabelle dar.

Das bedeutet, dass Sie mit Room-Entitäten Ihr Datenbankschema definieren können, ohne SQL-Code schreiben zu müssen.

Anatomie einer Entität

Sie definieren jede „Room“-Entität als eine mit @Entity annotierte Klasse. Eine Zimmerentität enthält Felder für jede Spalte in der entsprechenden Tabelle in der Datenbank, einschließlich einer oder mehrerer Spalten, aus denen der Primärschlüssel besteht.

Der folgende Code ist ein Beispiel für eine einfache Entität, die eine User-Tabelle mit Spalten für ID, Vorname und Nachname definiert:

Kotlin

@Entity
data class User(
    @PrimaryKey val id: Int,

    val firstName: String?,
    val lastName: String?
)

Java

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

    public String firstName;
    public String lastName;
}

Standardmäßig verwendet Room den Klassennamen als Namen der Datenbanktabelle. Wenn die Tabelle einen anderen Namen haben soll, legen Sie die Eigenschaft tableName der Annotation @Entity fest. Auf ähnliche Weise verwendet Room die Feldnamen standardmäßig als Spaltennamen in der Datenbank. Wenn eine Spalte einen anderen Namen haben soll, fügen Sie dem Feld die Annotation @ColumnInfo hinzu und legen Sie das Attribut name fest. Im folgenden Beispiel werden benutzerdefinierte Namen für eine Tabelle und ihre Spalten veranschaulicht:

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;
}

Primärschlüssel definieren

Jede Zimmerentität muss einen Primärschlüssel definieren, der jede Zeile in der entsprechenden Datenbanktabelle eindeutig identifiziert. Die einfachste Methode dafür besteht darin, eine einzelne Spalte mit @PrimaryKey zu annotieren:

Kotlin

@PrimaryKey val id: Int

Java

@PrimaryKey
public int id;

Zusammengesetzten Primärschlüssel definieren

Wenn Instanzen einer Entität durch eine Kombination aus mehreren Spalten eindeutig identifiziert werden müssen, können Sie einen zusammengesetzten Primärschlüssel definieren. Dazu listen Sie diese Spalten im Attribut primaryKeys von @Entity auf:

Kotlin

@Entity(primaryKeys = ["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;
}

Felder ignorieren

Standardmäßig erstellt „Room“ eine Spalte für jedes in der Entität definierte Feld. Wenn eine Entität Felder enthält, die nicht beibehalten werden sollen, können Sie diese mit @Ignore annotieren, wie im folgenden Code-Snippet gezeigt:

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;
}

In Fällen, in denen eine Entität Felder von einer übergeordneten Entität übernimmt, ist es in der Regel einfacher, die Eigenschaft ignoredColumns des Attributs @Entity zu verwenden:

Kotlin

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

@Entity(ignoredColumns = ["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 unterstützt verschiedene Arten von Anmerkungen, mit denen Sie in den Tabellen Ihrer Datenbank einfacher nach Details suchen können. Verwenden Sie die Volltextsuche, es sei denn, minSdkVersion Ihrer Anwendung ist kleiner als 16.

Volltextsuche unterstützen

Wenn Ihre Anwendung einen sehr schnellen Zugriff auf Datenbankinformationen über die Volltextsuche (FTS) benötigt, sichern Sie die Entitäten durch eine virtuelle Tabelle, die entweder das SQLite-Erweiterungsmodul FTS3 oder FTS4 verwendet. Wenn Sie diese Funktion, die ab Raum 2.1.0 verfügbar ist, verwenden möchten, fügen Sie einer bestimmten Entität die Annotation @Fts3 oder @Fts4 hinzu, wie im folgenden Code-Snippet gezeigt:

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;
}

Wenn eine Tabelle Inhalte in mehreren Sprachen unterstützt, verwenden Sie die Option languageId, um die Spalte anzugeben, in der die Sprachinformationen für jede Zeile gespeichert werden:

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 bietet mehrere andere Optionen zum Definieren von FTS-gestützten Entitäten, einschließlich Ergebnissortierung, Tokenizer-Typen und Tabellen, die als externe Inhalte verwaltet werden. Weitere Informationen zu diesen Optionen finden Sie in der Referenz zu FtsOptions.

Indexspezifische Spalten

Wenn Ihre Anwendung SDK-Versionen unterstützen muss, die keine FTS3- oder FTS4-tabellengestützten Entitäten unterstützen, können Sie trotzdem bestimmte Spalten in der Datenbank indexieren, um Abfragen zu beschleunigen. Wenn Sie einer Entität Indexe hinzufügen möchten, nehmen Sie das Attribut indices in die Annotation @Entity auf. Geben Sie dabei die Namen der Spalten an, die in den Index oder den zusammengesetzten Index aufgenommen werden sollen. Das folgende Code-Snippet veranschaulicht diesen Annotationsprozess:

Kotlin

@Entity(indices = [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;
}

Manchmal müssen bestimmte Felder oder Gruppen von Feldern in einer Datenbank eindeutig sein. Sie können dieses Eindeutigkeitsattribut erzwingen, indem Sie das Attribut unique einer @Index-Annotation auf true setzen. Das folgende Codebeispiel verhindert, dass eine Tabelle zwei Zeilen hat, die denselben Satz von Werten für die Spalten firstName und lastName enthalten:

Kotlin

@Entity(indices = [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-basierte Objekte einbeziehen

Ab Room 2.1.0 können Sie Java-basierte unveränderliche Wertklassen verwenden, die Sie mit @AutoValue als Entitäten in der Datenbank Ihrer Anwendung annotieren. Diese Unterstützung ist besonders hilfreich, wenn zwei Instanzen einer Entität als gleich angesehen werden, wenn ihre Spalten identische Werte enthalten.

Wenn Sie mit @AutoValue als Entitäten annotierte Klassen verwenden, können Sie die abstrakten Methoden der Klasse mit @PrimaryKey, @ColumnInfo, @Embedded und @Relation annotieren. Wenn Sie diese Annotationen verwenden, müssen Sie jedoch jedes Mal die Annotation @CopyAnnotations hinzufügen, damit Room die automatisch generierten Implementierungen der Methoden richtig interpretieren kann.

Das folgende Code-Snippet zeigt ein Beispiel für eine mit @AutoValue annotierte Klasse, die Room als Entität erkennt:

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);
    }
}