Defining data using Room entities

When using the
Room persistence library, you define
sets of related fields as entities. For each entity, a table is created within
the associated
Database object to
hold the items. You must reference the entity class through the
entities
array in the
Database class.

Java

To persist a field, Room must have access to it. You can make a field public, or
you can provide a getter and setter for it. If you use getter and setter
methods, keep in mind that they're based on JavaBeans conventions in Room.

Note: Entities can have either an empty constructor (if the corresponding
DAO class can access each
persisted field) or a constructor whose parameters contain types and names that
match those of the fields in the entity. Room can also use full or partial
constructors, such as a constructor that receives only some of the fields.

Use a primary key

Each entity must define at least 1 field as a primary key. Even when there is
only 1 field, you still need to annotate the field with the
@PrimaryKey
annotation. Also, if you want Room to assign automatic IDs to entities, you
can set the @PrimaryKey's
autoGenerate
property. If the entity has a composite primary key, you can use the
primaryKeys
property of the
@Entity annotation,
as shown in the following code snippet:

Java

By default, Room uses the class name as the database table name. If you want
the table to have a different name, set the
tableName
property of the
@Entity annotation,
as shown in the following code snippet:

Kotlin

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

Java

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

Caution: Table names in SQLite are case-insensitive.

Similar to the
tableName
property, Room uses the field names as the column names in the database. If
you want a column to have a different name, add the
@ColumnInfo
annotation to a field, as shown in the following code snippet:

Java

Ignore fields

By default, Room creates a column for each field that's defined in the entity.
If an entity has fields that you don't want to persist, you can annotate them
using @Ignore, as
shown in the following code snippet:

Java

Provide table search support

Room supports several types of annotations that make it easier for you to search
for details in your database's tables. Use full-text search unless your app's
minSdkVersion is less than 16.

Support full-text search

If your app requires very quick access to database information through full-text
search (FTS), have your entities backed by a virtual table that uses either
the FTS3 or FTS4 SQLite extension
module. To use this capability,
available in Room 2.1.0 and higher, add the
@Fts3 or
@Fts4 annotation to a given entity, as shown
in the following code snippet:

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") var id: Int,
@ColumnInfo(name = "first_name") var 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;
}

Note: FTS-enabled tables always use a primary key of type INTEGER and with the
column name "rowid". If your FTS-table-backed entity defines a primary key, it
must use that type and column name.

In cases where a table supports content in multiple languages, use the
languageId option to specify the column that stores language information for
each row:

Java

Room provides several other options for defining FTS-backed entities, including
result ordering, tokenizer types, and tables managed as external content. For
more details about these options, see the
FtsOptions reference.

Index specific columns

If your app must support SDK versions that don't allow for using FTS3- or
FTS4-table-backed entities, you can still index certain columns in the database
to speed up your queries. To add indices to an entity, include the
indices
property within the
@Entity annotation,
listing the names of the columns that you want to include in the index or
composite index. The following code snippet demonstrates this annotation
process:

Sometimes, certain fields or groups of fields in a database must be unique.
You can enforce this uniqueness property by setting the
unique
property of an @Index
annotation to true. The following code sample prevents a table from having
two rows that contain the same set of values for the firstName and
lastName columns:

Include AutoValue-based objects

Note: This capability is designed for use only in Java-based entities. To
achieve the same functionality in Kotlin-based entities, it's better to use
data
classes
instead.

In Room 2.1.0 and higher, you can use Java-based immutable value
classes,
which you annotate using @AutoValue, as entities in your app's database. This
support is particularly helpful when two instances of an entity are considered
to be equal if their columns contain identical values.

When using classes annotated with @AutoValue as entities, you can annotate the
class's abstract methods using @PrimaryKey, @ColumnInfo, @Embedded, and
@Relation. When using these annotations, however, you must include the
@CopyAnnotations annotation each time so that Room can interpret the methods'
auto-generated implementations properly.

The following code snippet shows an example of a class annotated with
@AutoValue that Room recognizes as an entity:

Define relationships between objects

Because SQLite is a relational database, you can specify relationships between
objects. Even though most object-relational mapping libraries allow entity
objects to reference each other, Room explicitly forbids this. To learn about
the technical reasoning behind this decision, see Understand why Room doesn't
allow object references.

Even though you cannot use direct relationships, Room still allows you to define
Foreign Key constraints between entities.

For example, if there's another entity called Book, you can define its
relationship to the User entity using the
@ForeignKey
annotation, as shown in the following code snippet:

Foreign keys are very powerful, as they allow you to specify what occurs when
the referenced entity is updated. For instance, you can tell SQLite to delete
all books for a user if the corresponding instance of User is deleted by
including onDelete = CASCADE
in the
@ForeignKey
annotation.

Note: SQLite handles
@Insert(onConflict = REPLACE)
as a set of REMOVE and REPLACE operations instead of a single UPDATE
operation. This method of replacing conflicting values could affect your
foreign key constraints. For more details, see the SQLite documentation for the
ON_CONFLICT clause.

Create nested objects

Sometimes, you'd like to express an entity or plain old Java object (POJO) as
a cohesive whole in your database logic, even if the object contains several
fields. In these situations, you can use the
@Embedded
annotation to represent an object that you'd like to decompose into its
subfields within a table. You can then query the embedded fields just as you
would for other individual columns.

For instance, our User class can include a field of type Address, which
represents a composition of fields named street, city, state, and
postCode. To store the composed columns separately in the table, include an
Address field in the User class that is annotated with
@Embedded, as
shown in the following code snippet:

The table representing a User object then contains columns with the following
names: id, firstName, street, state, city, and post_code.

Note: Embedded fields can also include other embedded fields.

If an entity has multiple embedded fields of the same type, you can keep each
column unique by setting the
prefix
property. Room then adds the provided value to the beginning of each column
name in the embedded object.