Definisci i dati utilizzando Entità camera

Quando utilizzi la libreria di persistenza delle stanze per archiviare i dati dell'app, definisci le entità che rappresentano gli oggetti che vuoi archiviare. Ogni entità corrisponde a una tabella nel database camera associato e ogni istanza di un'entità rappresenta una riga di dati nella tabella corrispondente.

Ciò significa che puoi utilizzare le entità camera per definire lo schema di database senza scrivere codice SQL.

Anatomia di un'entità

Puoi definire ogni entità Room come una classe annotata con @Entity. Un'entità Room include campi per ogni colonna nella tabella corrispondente del database, tra cui una o più colonne che costituiscono la chiave primaria.

Il codice seguente è un esempio di entità semplice che definisce una tabella User con colonne per ID, nome e cognome:

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

Per impostazione predefinita, la stanza virtuale utilizza il nome della classe come nome della tabella del database. Se vuoi che la tabella abbia un nome diverso, imposta la proprietà tableName dell'annotazione @Entity. Allo stesso modo, per impostazione predefinita la stanza virtuale utilizza i nomi dei campi come nomi delle colonne nel database. Se vuoi che una colonna abbia un nome diverso, aggiungi l'annotazione @ColumnInfo al campo e imposta la proprietà name. L'esempio seguente mostra i nomi personalizzati di una tabella e delle relative colonne:

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

Definisci una chiave primaria

Ogni entità Room deve definire una chiave primaria che identifichi in modo univoco ogni riga nella tabella di database corrispondente. Il modo più semplice per farlo è annotare una singola colonna con @PrimaryKey:

Kotlin

@PrimaryKey val id: Int

Java

@PrimaryKey
public int id;

Definisci una chiave primaria composita

Se hai bisogno che le istanze di un'entità vengano identificate in modo univoco da una combinazione di più colonne, puoi definire una chiave primaria composita elencando queste colonne nella proprietà primaryKeys di @Entity:

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

Ignora campi

Per impostazione predefinita, Stanza virtuale crea una colonna per ogni campo definito nell'entità. Se un'entità contiene campi che non vuoi mantenere, puoi annotarli utilizzando @Ignore, come mostrato nel seguente snippet di codice:

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

Nei casi in cui un'entità eredita i campi da un'entità padre, in genere è più facile utilizzare la proprietà ignoredColumns dell'attributo @Entity:

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 supporta diversi tipi di annotazioni che semplificano la ricerca dei dettagli nelle tabelle del database. Utilizza la ricerca a testo intero, a meno che il valore minSdkVersion della tua app non sia inferiore a 16.

Supporto della ricerca nel testo completo

Se la tua app richiede un accesso molto rapido alle informazioni del database tramite la ricerca a testo completo (FTS), fai in modo che le tue entità siano supportate da una tabella virtuale che utilizza il modulo di estensione SQLite FTS3 o FTS4. Per utilizzare questa funzionalità, disponibile nella stanza 2.1.0 e nelle versioni successive, aggiungi l'annotazione @Fts3 o @Fts4 a una determinata entità, come mostrato nel seguente snippet di codice:

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

Se una tabella supporta contenuti in più lingue, utilizza l'opzione languageId per specificare la colonna in cui sono archiviate le informazioni sulla lingua per ogni riga:

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 offre diverse altre opzioni per definire le entità supportate da FTS, tra cui l'ordinamento dei risultati, i tipi di tokenizzatore e le tabelle gestite come contenuti esterni. Per ulteriori dettagli su queste opzioni, consulta la documentazione di FtsOptions.

Colonne specifiche dell'indice

Se la tua app deve supportare versioni dell'SDK che non supportano le entità basate su tabella FTS3 o FTS4, puoi comunque indicizzare determinate colonne del database per velocizzare le query. Per aggiungere indici a un'entità, includi la proprietà indices all'interno dell'annotazione @Entity, elencando i nomi delle colonne che vuoi includere nell'indice o nell'indice composto. Il seguente snippet di codice dimostra questo processo di annotazione:

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

A volte, alcuni campi o gruppi di campi di un database devono essere univoci. Puoi applicare questa proprietà di univocità impostando la proprietà unique di un'annotazione @Index su true. Il seguente esempio di codice impedisce che una tabella abbia due righe contenenti lo stesso insieme di valori per le colonne firstName e lastName:

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

Includi oggetti basati su valori automatici

Nella stanza 2.1.0 e nelle versioni successive, puoi utilizzare classi di valore immutabili basate su Java, a cui puoi annotare utilizzando @AutoValue, come entità nel database della tua app. Questo supporto è particolarmente utile quando due istanze di un'entità vengono considerate uguali se le relative colonne contengono valori identici.

Quando utilizzi classi annotate con @AutoValue come entità, puoi annotare i metodi astratti della classe utilizzando @PrimaryKey, @ColumnInfo, @Embedded e @Relation. Quando utilizzi queste annotazioni, tuttavia, devi includere l'annotazione @CopyAnnotations ogni volta in modo che Room possa interpretare correttamente le implementazioni generate automaticamente dei metodi.

Il seguente snippet di codice mostra un esempio di classe annotata con @AutoValue che Room riconosce come entità:

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