Room官方文档(翻译)1.使用Room实体定义数据

2,675 阅读5分钟

当使用 Room 库的时候,你可以将一些字段集合定义为实体.对于每一个实体,在与之相关联的数据库对象中会创建一张表来保存这些字段。你必须通过 Database 类中的 entities 列表来引用这些实体。 以下代码展示了如何定义实体

@Entity
data class User(
    @PrimaryKey var id: Int,
    var firstName: String?,
    var lastName: String?
)

要保留某个成员变量,Room必须有权限访问它,它要么是 public 的,要么提供了 getter/setter 方法(基于 JavaBeans 约定而来)

实体的构造函数既可以是无参的(只要 DAO 类能够访问到要保留的字段);也可以包含参数(如果你要保存这些参数对应的字段的话)。

使用主键

每个实体必须定义一个主键,即使它只包含一个成员变量,你仍然需要将这个成员变量用@PrimaryKey标记。如果你想让主键自增,你可以通过@PrimaryKey的 autoGenerate 属性设置。如果你的实体需要使用复合主键,你可以通过@Entity注解的 primaryKeys 属性来达到目的,如下面的代码块所示:

@Entity(primaryKeys = arrayOf("firstName", "lastName"))
data class User(
    val firstName: String?,
    val lastName: String?
)

Room默认使用类名作为数据表的名称,如果你想自定义表名,通过@Entity注解的 tableName 属性设置。

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

注意:表名在 SQLite 中是不区分大小写的

和 tableName 属性一样, Room使用成员变量作为数据库的字段名。如果你想自定义字段名,通过@ColumnInfo注解来设置

@Entity(tableName = "users")
data class User (
    @PrimaryKey val id: Int,
    @ColumnInfo(name = "first_name") val firstName: String?,
    @ColumnInfo(name = "last_name") val lastName: String?
)

忽略成员变量

Room 默认为实体类的所有成员变量创建对应的字段,如果你不想保留某些成员变量,可以使用@Ignore注解

@Entity
data class User(
    @PrimaryKey val id: Int,
    val firstName: String?,
    val lastName: String?,
    @Ignore val picture: Bitmap?
)

为忽略某些继承自父类的变量,你可以通过@Entity注解的 ignoredColumns 属性设置

open class User {
    var picture: Bitmap? = null
}

@Entity(ignoredColumns = arrayOf("picture"))
data class RemoteUser(
    @PrimaryKey val id: Int,
    val hasVpn: Boolean
) : User()

提供表搜索支持

Room提供了几种类型的注解,可以更加简单地实现数据表的详情检索。在 minSdkVersion >= 16 的app上使用全文检索。

提供全文检索( full-text search)

如果你的 app 需要通过全文检索(FTS)快速访问数据库,让你的实体使用 FTS3 或者 FTS4 从而得到虚拟表的支持。为了使用这个特性 ,使用 Room 2.1.0 或者更高版本,在实体上添加@Fts3注解或者@Fts4注解。

// 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") val id: Int,
    @ColumnInfo(name = "first_name") val firstName: String?
)

启用了 FTS 的表总是使用类型为 Integer ,名称为 "rowid"的主键,如果你的实体支持了 FTS ,那么主键也得弄成这样。

如果表支持多种语言的内容,使用 languageId 选项指定列为每一个存储语言信息。

@Fts4(languageId = "lid")
@Entity(tableName = "users")
data class User(
    // ...
    @ColumnInfo(name = "lid") val languageId: Int
)

Room为支持 FTS 的实体还提供了一些其他选项,包括结果排序、令牌生成器类型等等,FtsOptions

列索引

如果你的 app 必须支持无法使用 FTS3或者 FTS4的版本,你仍然可以通过索引提升查询速度。通过@Entity注解的indices属性设置索引,包括索引和复合索引。

@Entity(indices = arrayOf(Index(value = ["last_name", "address"])))
data class User(
    @PrimaryKey val id: Int,
    val firstName: String?,
    val address: String?,
    @ColumnInfo(name = "last_name") val lastName: String?,
    @Ignore val picture: Bitmap?
)

有时,有几个字段的组合值必须是唯一的,你可以通过@Index注解的 unique 属性来达到目的。

@Entity(indices = arrayOf(Index(value = ["first_name", "last_name"],
        unique = true)))
data class User(
    @PrimaryKey val id: Int,
    @ColumnInfo(name = "first_name") val firstName: String?,
    @ColumnInfo(name = "last_name") val lastName: String?,
    @Ignore var picture: Bitmap?
)

包括基于AutoValue的对象

ps:

这里的AutoValue指的是一款代码生成工具。

google/auto

华山论剑之JAVA三大代码生成工具:Lombok、AutoValue和Immutables


Note:该功能仅设计用于基于Java的实体,为了在Kotlin中实现相同的功能,最好使用Data类

在Room 2.1.0及更高版本,你可以使用@AutoValue注解的,基于Java的不可变值类作为数据库中的实体。如果两个实例因为它们的列含有相同的值而被认为是相等的,此时这种支持就显得非常有用了。

当使用@AutoValue注释的类作为实体时,可以使用@PrimaryKey, @ColumnInfo, @Embedded,和 @Relation.但当使用这些注解时,你必须同时加上@CopyAnnotations注解,以便Room可以正确解释方法的自动生成实现。

@AutoValue
@Entity
public abstract class User {
    // Supported annotations must include `@CopyAnnotations`.
    @CopyAnnotations
    @PrimaryKey
    public abstract long getId();

    public abstract String getFirstName();
    public abstract String getLastName();

    // Room uses this factory method to create User objects.
    public static User create(long id, String firstName, String lastName) {
        return new AutoValue_User(id, firstName, lastName);
    }
}

Room官方文档(翻译)0.概览

Room官方文档(翻译)1.使用Room实体定义数据

Room官方文档(翻译)2.定义对象间的关系

Room官方文档(翻译)3.在数据库中创建视图

Room官方文档(翻译)4.使用Room DAOs访问数据

Room官方文档(翻译)5.迁移数据库

Room官方文档(翻译)6.测试数据库

Room官方文档(翻译)7.使用Room引用复杂数据