使用 Room 實體定義資料

使用 Room 持續性程式庫儲存應用程式的資料時,您可以定義實體來代表要儲存的物件。每個實體都會對應到相關聯的 Room 資料庫中的一個資料表,而實體的每個例項則代表對應資料表中的一列資料。

使用 Room 實體定義資料庫結構定義時,不必編寫任何 SQL 程式碼。

實體剖析

您可以將每個 Room 實體定義為已加上 @Entity 註解的類別。Room 實體包含資料庫中對應資料表內每個資料欄的屬性,包括構成主鍵的一或多個資料欄。

以下程式碼是實體範例,定義了內含 ID、名字和姓氏資料欄的 User 資料表:

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

根據預設,Room 會使用類別名稱做為資料庫資料表的名稱。如果想讓資料表使用不同名稱,請設定 @Entity 註解的 tableName 屬性。同樣地,Room 預設會使用屬性名稱做為資料庫中的資料欄名稱。如要為資料欄指定不同名稱,請為屬性加上 @ColumnInfo 註解,並設定 name 屬性。以下範例顯示資料表及其資料欄的自訂名稱:

@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 實體定義主鍵,藉此在資料庫的對應資料表中識別各個資料列。方法是使用 @PrimaryKey 為單一資料欄加上註解:

@PrimaryKey val id: Int

定義複合式主鍵

如果需要利用多個資料欄的組合來識別實體的執行個體,建議您定義「複合式主鍵」,方法是在 @EntityprimaryKeys 屬性中列出這些資料欄:

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

忽略屬性

根據預設,Room 會為實體中定義的每個屬性建立一個資料欄。如要防止 Room 持久保留屬性,請使用 @Ignore 註解為屬性加上註解:

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

如果實體沿用上層實體的屬性,請使用 @Entity 註解的 ignoredColumns 屬性:

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

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

Room 支援多種註解,可讓您搜尋資料庫表格中的詳細資料。

支援全文搜尋功能

如果應用程式需要快速全文搜尋 (FTS),請利用虛擬資料表支援實體。使用 FTS3 或 FTS4 SQLite 擴充功能,或是 FTS5 SQLite 擴充功能

如要使用這項功能,請將 @Fts3@Fts4@Fts5 註解新增至實體。

// Use `@Fts3` only if your app has strict disk space requirements.
@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 an INTEGER type and column name "rowid".
    @PrimaryKey @ColumnInfo(name = "rowid") val id: Long,
    @ColumnInfo(name = "first_name") val firstName: String
)

如要自訂 FTS 資料表中資料庫資訊的權杖化方式,請使用 tokenizer 選項。Room 透過 FtsOptions 提供多個內建權杖化工具,包括 TOKENIZER_SIMPLETOKENIZER_PORTERTOKENIZER_UNICODE61

@Fts4(tokenizer = FtsOptions.TOKENIZER_UNICODE61)
@Entity(tableName = "users")
data class User(
    @PrimaryKey @ColumnInfo(name = "rowid") val id: Long,
    @ColumnInfo(name = "first_name") val firstName: String
)

Room 提供多種其他選項來定義受 FTS 支援的實體,包括結果排序、從資料欄移除索引,以及當做外部內容管理的資料表。如要進一步瞭解這些選項,請參閱 FtsOptions 參考資料。

索引專用的資料欄

如果您使用 AndroidSQLiteDriver,且需要支援不允許使用受 FTS3、FTS4 或 FTS5 資料表支援的實體的 SDK 版本,您仍可為資料庫中的特定資料欄建立索引,以加快查詢速度。如果您使用 BundledSQLiteDriver,無論 Android SDK 版本為何,Room 都支援所有 FTS 版本。

如要為實體加入索引,請在 @Entity 註解中加入 indices 屬性。列出要在索引或複合式索引中加入的資料欄名稱。下列程式碼片段說明如何新增索引:

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

有時,資料庫中的特定資料欄或資料欄群組必須包含不重複的值。如要強制執行這項不重複屬性,請將 @Index 註解的 unique 屬性設為 true。以下程式碼範例說明如何強制執行這項唯一性:

@Entity(indices = [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,
)