本文翻译自官网
使用Room进行持久化存储---综述
通过 Room entities 定义数据 ---Room 系列(1)
使用 Room 的 DAO 访问数据---Room 系列(2)
Android 中使用 Room 实践
当使用 Room 持久化库 的时候,我们需要定义一系列相关的成员作为 entities 。每个 entity 将被映射为一个 Database 中的 table。
默认情况下,Room 会为 Entity 中的每个成员创建一个 column。如果你不想对其中的某些成员进行持久化,可以使用 @Ingore 注解。
下面代码块,展示了怎样定义一个 entity:
@Entity
class User {
@PrimaryKey
public int id;
public String firstName;
public String lastName;
@Ignore
Bitmap picture;
}
持久化成员之后,Room 必须有能力能够访问到它们。这就意味着需要把该成员设置为 public ,或者提供 getter、setter 方法能够访问到。
使用主键(primary key)
每个 entity 必须至少定义一个成员作为主键。也就是说,当仅有一个成员的时候,需要使用 @PrimaryKey 对该成员进程注解。如果你希望 Room 给 entity 设置一个自增的 id , 可以设置 @PrimaryKey 的 autoGenerate 属性。如果一个 entity 需要复合主键(译注:多个字段共同构成主键,主要是考虑到没有id作为你主键,但是又要保证主键唯一性的问题),你可以使用 @Entity 注解的 primaryKeys 属性。
@Entity(primaryKeys = {"firstName", "lastName"})
class User {
public String firstName;
public String lastName;
@Ignore
Bitmap picture;
}
@Entity
public class User {
@PrimaryKey(autoGenerate = true)
private int uid;
@ColumnInfo(name = "first_name")
private String firstName;
@ColumnInfo(name = "last_name")
private String lastName;
// Getters and setters are ignored for brevity,
// but they're required for Room to work.
}
默认情况下, Room 将使用类名作为 table 的名字,当然,你也可以自己设定名字:
@Entity(tableName = "users")
class User {
...
}
注意,table 名字在 SQLite 中是大小写不敏感的。
类似于上面的 tableName 属性,Room 默认使用成员名作为列名,当然,你也可以通过 @ColumnInfo 自己设定:
@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;
}
注解索引和设置唯一性
为了在 entity 中建立索引,需要在 @Entity 注解中添加 indices 属性,列出需要索引的列名。
@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;
}
有时,对一些成员需要保证唯一性。你可以在 @Index 注解中设置 unique 属性为 true。
@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;
}
定义对象之间的关系
SQLite 是一种关系型数据库。你可以指定 对象 之间的关系。虽然很多 ORM 库(对象关系映射库)允许 entity 对象相互引用,但是这在 Room 是明确禁止的。
即使你不能直接使用这些直接关系,但是 Room 允许你定义在 entity 之间的外键。
举个栗子,假如这里有另外一个叫做 Book 的 entity,你可以通过 @ForeignKey 定义它和 User 实体的关系。
@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;
}
外键是很强大的,它们允许你指定 当引用的 entity 发生更新的时候会发生什么。比如,你可以通过在 @ForeignKey 注解中,添加 onDelete = CASCADE ,以告诉SQLite,如果一个 User 实体被删除的时候,删除他所有的书籍。
创建嵌套对象
以上,我们在成员都是基础类型或者 string 类型的数据。 但是有时,在逻辑上,我们希望将某某些成员封装一个紧密结合的内部实体。此时可以使用 @Embedded 注解表达这一类内部嵌套的实体。
在进行查询访问的时候,内部实体的每个成员还是需要作为一个单独的列来访问它们。
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;
}
上述表中,有一下列:id, firstName, street, state, city, and post_code。
注意,嵌套之中还可以添加嵌套。
如果在 entity 中包含多个同类型的嵌套,这时候可以通过设置 prefix 属性的方式加以区分:
@Embedded(prefix = "addr1")
public Address address1;
@Embedded(prefix = "addr2")
public Address address2;
Room 会把这个 prefix 作为前缀添加到每个列名前面。
(译注:通过insert方法插入嵌套结构数据之后示意图如下)