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.
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. You
must reference the entity class through the
entities
array in the
Database class.
The following code snippet shows how to define an entity:
@Entity
class User {
@PrimaryKey
public int id;
public String firstName;
public String lastName;
@Ignore
Bitmap picture;
}
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.
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:
@Entity(primaryKeys = {"firstName", "lastName"})
class User {
public String firstName;
public String lastName;
@Ignore
Bitmap picture;
}
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:
@Entity(tableName = "users")
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:
@Entity(tableName = "users")
class User {
@PrimaryKey
public int id;
@ColumnInfo(name = "first_name")
public String firstName;
@ColumnInfo(name = "last_name")
public String lastName;
@Ignore
Bitmap picture;
}
Annotate indices and uniqueness
Depending on how you access the data, you might want to index certain fields
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:
@Entity(indices = {@Index("name"),
@Index(value = {"last_name", "address"})})
class User {
@PrimaryKey
public int id;
public String firstName;
public String address;
@ColumnInfo(name = "last_name")
public String lastName;
@Ignore
Bitmap picture;
}
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:
@Entity(indices = {@Index(value = {"first_name", "last_name"},
unique = true)})
class User {
@PrimaryKey
public int id;
@ColumnInfo(name = "first_name")
public String firstName;
@ColumnInfo(name = "last_name")
public String lastName;
@Ignore
Bitmap picture;
}
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:
@Entity(foreignKeys = @ForeignKey(entity = User.class,
parentColumns = "id",
childColumns = "user_id"))
class Book {
@PrimaryKey
public int bookId;
public String title;
@ColumnInfo(name = "user_id")
public int userId;
}
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.
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:
class Address {
public String street;
public String state;
public String city;
@ColumnInfo(name = "post_code")
public int postCode;
}
@Entity
class User {
@PrimaryKey
public int id;
public String firstName;
@Embedded
public Address address;
}
The table representing a User object then contains columns with the following
names: id, firstName, street, state, city, and post_code.
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.


