[译] 通过 Room entities 定义数据 ---Room 系列(1)

本文翻译自官网
使用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方法插入嵌套结构数据之后示意图如下)

db.userDao().insertAll(user)

你可能感兴趣的:([译] 通过 Room entities 定义数据 ---Room 系列(1))