使用 Room entities 定義資料 (Room)

使用 Room 時,可以將相關的屬性定義為實體(entities)。

對於每個實體,將會創建一個資料表來保存項目在 Database 物件中,必須透過 Database 類別中的 entities 陣列來引用實體類別。

以下示範如何定義一個實體(entity)

@Entity  
public class User {
@PrimaryKey
public int id;

public String firstName;
public String lastName;
}

為了保存屬性,Room 必須去存取它。可以透過將該屬性設定為 public 或提供 getter 和 setter 存取器。若是使用存取器必須注意該存取器必須符合 JavaBeans 的命名規則。

注意:
實體(Entity)可以有一個空構造函數(如果相應的 DAO 類別可以訪問每個持久化字段),或者一個構造函數,其參數包含與實體中的屬性匹配的類型和名稱。Room 也可以使用完整或部分構造函數,例如只接收某些屬性的構造函數。

Use a primary key


每個實體必須至少定義一個屬性作為主鍵。即使只有一個屬性,仍需要使用 @PrimaryKey 註釋來註釋該屬性。

此外,如果希望 Room 為實體分配自動 ID,可以設定 @PrimaryKey 的 autoGenerate 屬性。

如果實體具有複合主鍵,則可以使用 @Entity 註釋的 primaryKeys 屬性,如以下代碼段所示:
@Entity(primaryKeys = {"firstName", "lastName"})  
public class User {
public String firstName;
public String lastName;
}

 

Room 預設使用類別名稱作為資料表名稱。如果希望資料表使用不同的名稱,可以設定  @Entity 註釋的 tableName 屬性,如以下代碼段所示:
@Entity(tableName = "users")  
public class User {
// ...
}

注意:
資料表名稱是區分大小寫的

 

類似於 tableName,Room 使用屬性名稱作為資料庫中的列名稱。如果希望列具有不同的名稱,請將 @ColumnInfo 註釋加到屬性中,如以下代碼段所示:
@Entity(tableName = "users")  
public class User {
@PrimaryKey
public int id;

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

@ColumnInfo(name = "last_name")
public String lastName;
}

 

Ignore fileds


預設情況下,Room 會為實體中定義的每個屬性都創建一列。如果實體具有不想保存的屬性,則可以使用 @Ignore 對其進行註釋,如以下代碼段所示:
@Entity  
public class User {
@PrimaryKey
public int id;

public String firstName;
public String lastName;

@Ignore
Bitmap picture;
}

 

如果實體從另一個實體(父實體)繼承屬性,則通常使用 @Entity 屬性的 ignoredColumns:
@Entity(ignoredColumns = "picture")  
public class RemoteUser extends User {
@PrimaryKey
public int id;

public boolean hasVpn;
}

 

Provide table search support


Room 支持多種類型的註釋,可以更輕鬆地搜索資料表中的詳細信息。除非應用程序的 minSdkVersion 小於 16,否則請使用全文搜索(full-text search)。

Support full-text search


如果應用程序需要通過全文搜索(FTS)快速訪問數據庫信息,就讓實體由使用 FTS3 或 FTS4 SQLite 擴展模塊的虛擬表支持。

要使用全文搜索,必須在 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")
public 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")
public int id;

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

注意:啟用 FTS 的資料表必須使用 INTEGER 類型的主鍵和列名''rowid''。如果 FTS 資料表支持的實體定義主鍵,則它必須使用該類型和列名稱。

 

如果資料表支持多種語言的內容,請使用 languageId 選項指定存儲每行語言信息的列:
@Fts4(languageId = "lid")  
@Entity(tableName = "users")
public class User {
// ...

@ColumnInfo(name = "lid")
int languageId;
}

 

Room 提供了其他幾個用於定義FTS支持的實體選項,包括結果排序(result ordering),tokenizer 類型(tokenizer types)和作為外部內容管理的資料表。有關這些選項的更多詳細信息,請參閱 FtsOptions 參考。

 

Index specific columns


如果應用程序必須支持不允許使用 FTS3 或 FTS4 資料表支持實體的 SDK 版本,仍然可以索引數據庫中的某些列以加快查詢速度。

要向實體添加索引,請在 @Entity 註釋中包含 indices 屬性,列出要包含在索引或複合索引中的列的名稱。如下所示
@Entity(indices = {@Index("name"),  
@Index(value = {"last_name", "address"})})
public 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 來強制實施此唯一性屬性。

以下代碼示例可防止表具有兩行,這些行包含 firstName 和 lastName 列的相同值集:
@Entity(indices = {@Index(value = {"first_name", "last_name"},  
unique = true)})
public class User {
@PrimaryKey
public int id;

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

@ColumnInfo(name = "last_name")
public String lastName;

@Ignore
Bitmap picture;
}

 

Include AutoValue-based objects


注意:
這個特性只用於 java-based entities,不支援 Kotlin。

在 Room 2.1.0 及更高版本中,可以使用基於 Java 的不可變值類(使用 @AutoValue 進行註釋)作為數據庫中的實體。

如果實體的兩個實例的列包含相同的值,則此支持特別有用。

使用帶 @AutoValue 註釋的類別作為實體時,可以使用 @PrimaryKey,@ColumnInfo,@ Embedded 和 @Relation 註釋類別的抽象方法。但是,在使用這些註釋時,每次都必須包含 @CopyAnnotations 註釋,以便 Room 可以正確解釋方法的自動生成實現。

以下代碼段顯示了一個使用 @AutoValue 註釋類別的示例,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);
}
}

 

Define relationships between objects


由於 SQLite 是關係數據庫,因此可以指定物件之間的關係。儘管大多數對象關係映射庫允許實體對象相互引用,但 Room 明確禁止這樣做。即使不能使用直接關係,Room 仍允許在實體之間定義外鍵約束。

例如,如果有另一個名為 Book 的實體,可以使用 @ForeignKey 註釋定義其與 User 實體的關係,如以下代碼段所示:
@Entity(foreignKeys = @ForeignKey(entity = User.class,  
parentColumns = "id",
childColumns = "user_id"))
public class Book {
@PrimaryKey
public int bookId;

public String title;

@ColumnInfo(name = "user_id")
public int userId;
}

外鍵非常強大,因為它們允許指定更新引用實體時發生的情況。

例如,如果通過在 @ForeignKey 註釋中包含 onDelete = CASCADE 來刪除相應的 User 實例,則可以告訴 SQLite 刪除用戶的所有書籍。

注意:
SQLite 將 @Insert(onConflict = REPLACE)作為一組 REMOVE 和 REPLACE 操作處理,而不是單個 UPDATE 操作。這種替換衝突值的方法可能會影響外鍵約束。

 

Create nested objects


有時候希望將實體或 POJO 表達為資料庫邏輯中的一個整體,即使該物件包含多個屬性。

在這些情況下,可以使用 @Embedded 註釋來表示要分解到資料表內子字屬性的物件。然後,可以像查找其他單個列一樣查詢嵌入屬性(Embedded filed)。

例如,User 類別可以包含 Address 類別的屬性,而 Address 也有其屬性為 street,city,state 和 postCode 屬性。

User.java
@Entity  
public class User {
@PrimaryKey
public int id;

public String firstName;

@Embedded
public Address address;
}

Address.java
public class Address {  
public String street;
public String state;
public String city;

@ColumnInfo(name = "post_code")
public int postCode;
}

然後,表示 User 物件的資料表包含具有以下名稱的列:id,firstName,street,state,city 和 post_code。

注意:
嵌入屬性(Embedded filed)可以再包含其它嵌入屬性(Embedded filed)

如果實體具有多個相同類型的嵌入屬性,則可以通過設置 prefix 屬性使每個列保持唯一。然後,Room 將提供的值添加到嵌入屬性中每個列名稱的開頭。

Orignal From: 使用 Room entities 定義資料 (Room)

0 意見:

張貼留言

Twitter Delicious Facebook Digg Stumbleupon Favorites More

 
Design by Free WordPress Themes | Bloggerized by Lasantha - Premium Blogger Themes | Affiliate Network Reviews