Skip to content

实体类介绍

前面的例子中,我们使用了User实体类。 这里再创建一些实体类,介绍表名,列名,主键的配置方法和常见问题。

表名

默认情况下,Room 将类名称用作数据库表名称。 如果我们要设置不同的表名,设置 @Entity 注释的 tableName 属性

@Entity(tableName = "user-extra-2")
public class User2 {/*...*/}

像这样设置表名为user-extra-2

主键

每个实体必须将至少1个字段定义为主键。 即使只有1个字段,仍然需要为该字段添加@PrimaryKey注释。

@Entity(tableName = "user-extra-2")
public class User2 {

    @NonNull
    @PrimaryKey
    @ColumnInfo(name = "first_name")
    public String firstName;
    // ...
}

如果实体具有复合主键,在@Entity里指定primaryKeys。指定的列名,要和后面定义的列名一致。

@Entity(tableName = "user-extra-2", primaryKeys = {"first_name", "lastName"})
public class User2 {

    @NonNull
    @ColumnInfo(name = "first_name")
    public String firstName;

    @NonNull
    @ColumnInfo(defaultValue = "Fisher")
    public String lastName;

示例中,2个列名分别是first_namelastName。 这里仅是示例。实际项目中,我们还是统一用一种命名风格比较好。

此外,如果想让 Room 为实体分配自动 ID,则可以设置 @PrimaryKeyautoGenerate 属性。

@Entity(tableName = "user-extra-2")
public class User2 {
    @PrimaryKey(autoGenerate = true)
    public long uid;
    // ...
}

重复指定主键

假设我们在@Entity中定义了primaryKeys,又在字段上使用@PrimaryKey指定主键

@Entity(tableName = "user-extra-2", primaryKeys = {"uid"})
public class User2 {
    @PrimaryKey
    public long uid;
//...
}

会在编译时报错

错误: You cannot have multiple primary keys defined in an Entity. If you want to declare a composite primary key, you should use @Entity#primaryKeys and not use @PrimaryKey. Defined Primary Keys: PrimaryKey[uid], PrimaryKey[uid]
public class User2 {

主键不能为空

前面我们用long作为主键。现在如果用String来做主键,需要加上@NonNull注解。否则如下代码会在编译时报错

@Entity(tableName = "user-extra-2")
public class User2 {
    public long uid;

    @PrimaryKey
    @ColumnInfo(name = "first_name")
    public String firstName;

报错信息,要给主键加上@NonNull注解

错误: You must annotate primary keys with @NonNull. "firstName" is nullable. SQLite considers this a bug and Room does not allow it. See SQLite docs for details: https://www.sqlite.org/lang_createtable.html
    public String firstName;

加上注解后

// ...
@NonNull
@PrimaryKey
@ColumnInfo(name = "first_name")
public String firstName;
// ...

primaryKeys范围

假设我们指定的关键字段和指定的列名不一致

@Entity(tableName = "user-extra-2", primaryKeys = {"firstName"})
public class User2 {
    @NonNull
    @ColumnInfo(name = "first_name")
    public String firstName;
    // ...
}

编译时会报错

错误: firstName referenced in the primary key does not exists in the Entity. Available column names:uid, first_name, last_name, createTime
public class User2 {

因为我们指定了列名first_name,primaryKeys的可用值必须在列名范围内。

列名

上文我们可以注意到,列名默认是属性的名字,也可以用@ColumnInfo中的name来重新定义列名。 也可以给这一列使用defaultValue添加默认值。

    @ColumnInfo(name = "first_name")
    public String firstName;

    @ColumnInfo(defaultValue = "Fisher")
    public String lastName;

忽略字段

默认情况下,Room 会为实体中定义的每个字段创建一个列。 如果某个实体中有您不想保留的字段,则可以使用 @Ignore为这些字段添加注释,如以下代码段所示:

@Entity
public class User2 {
    @PrimaryKey
    public int id;
    // ...
    @Ignore
    Bitmap picture;
}

如果实体继承了父实体的字段,则使用 @Entity 属性的 ignoredColumns 属性通常会更容易:

@Entity(ignoredColumns = "picture")
public class User3 extends User2 {
    @PrimaryKey
    public int id;
    // ...
}