Xác định dữ liệu bằng các thực thể Room

Khi sử dụng Thư viện lưu trữ Room để lưu trữ dữ liệu của ứng dụng, bạn xác định các bản sao đại diện cho đối tượng mà bạn muốn lưu trữ. Mỗi thực thể tương ứng với một bảng trong cơ sở dữ liệu Room được liên kết và mỗi bản sao của một thực thể đại diện cho một hàng dữ liệu trong bảng tương ứng.

Điều đó có nghĩa là bạn có thể sử dụng các thực thể Room để xác định giản đồ cơ sở dữ liệu của mình mà không cần viết bất kỳ mã SQL nào.

Phân tích một thực thể

Bạn xác định mỗi thực thể Room là một lớp được chú thích bằng @Entity. Thực thể Room bao gồm các trường cho từng cột trong bảng tương ứng trong cơ sở dữ liệu, bao gồm một hoặc nhiều cột gồm khoá chính.

Mã sau đây là ví dụ về một thực thể đơn giản xác định một bảng User với các cột cho mã nhận dạng, họ và tên:

Kotlin

@Entity
data class User(
    @PrimaryKey val id: Int,

    val firstName: String?,
    val lastName: String?
)

Java

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

    public String firstName;
    public String lastName;
}

Theo mặc định, Room sử dụng tên lớp này làm tên bảng cơ sở dữ liệu. Nếu bạn muốn bảng có tên khác, đặt thuộc tính tableName của chú thích @Entity. Tương tự, theo mặc định, Room sử dụng tên trường làm tên cột trong cơ sở dữ liệu. Nếu bạn muốn một cột có tên khác, hãy thêm chú thích @ColumnInfo vào trường và đặt thuộc tính name. Ví dụ sau đây minh hoạ tên tuỳ chọn cho bảng và cột:

Kotlin

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

Java

@Entity(tableName = "users")
public class User {
    @PrimaryKey
    public int id;

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

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

Xác định khoá chính

Mỗi thực thể Room phải xác định một khoá chính giúp nhận dạng duy nhất từng hàng trong bảng cơ sở dữ liệu tương ứng. Cách nhanh nhất để thực hiện việc này là chú thích từng cột bằng @PrimaryKey:

Kotlin

@PrimaryKey val id: Int

Java

@PrimaryKey
public int id;

Xác định khoá chính tổng hợp

Nếu muốn các bản sao của một thực thể được xác định là duy nhất bởi một tổ hợp gồm nhiều cột, bạn có thể xác định một khoá chính tổng hợp bằng cách liệt kê các cột đó trong thuộc tính primaryKeys của @Entity:

Kotlin

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

Java

@Entity(primaryKeys = {"firstName", "lastName"})
public class User {
    public String firstName;
    public String lastName;
}

Bỏ qua các trường

Theo mặc định, Room sẽ tạo một cột cho mỗi trường được xác định trong thực thể. Nếu một thực thể có các trường mà bạn không muốn lưu trữ, bạn có thể chú thích các trường đó bằng cách sử dụng @Ignore, như được thấy trong đoạn mã sau:

Kotlin

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

Java

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

    public String firstName;
    public String lastName;

    @Ignore
    Bitmap picture;
}

Trong trường hợp một thực thể kế thừa các trường từ thực thể mẹ, thì thường sẽ dễ dàng hơn khi sử dụng thuộc tính ignoredColumns của thuộc tính @Entity:

Kotlin

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

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

Java

@Entity(ignoredColumns = "picture")
public class RemoteUser extends User {
    @PrimaryKey
    public int id;

    public boolean hasVpn;
}

Room hỗ trợ một số loại chú thích giúp bạn tìm kiếm thông tin chi tiết trong bảng cơ sở dữ liệu của mình dễ dàng hơn. Sử phương thức tìm kiếm toàn bộ văn bản trừ khi minSdkVersion của ứng dụng của bạn dưới 16.

Hỗ trợ phương thức tìm kiếm toàn bộ văn bản

Nếu ứng dụng của bạn đòi hỏi quyền truy cập cực nhanh vào thông tin cơ sở dữ liệu thông qua phương thức tìm kiếm toàn bộ văn bản (FTS), hãy để các thực thể được hỗ trợ bởi một bảng ảo sử dụng FTS3 hoặc FTS4Mô-đun phần mở rộng SQLite , Để sử dụng tính năng này, trong Room từ 2.1.0 trở lên, hãy thêm chú thích @Fts3 hoặc @Fts4 vào một thực thể cụ thể, như trong đoạn mã sau đây:

Kotlin

// 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?
)

Java

// 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;
}

Trong trường hợp bảng hỗ trợ nội dung bằng nhiều ngôn ngữ, hãy sử dụng tuỳ chọn languageId để chỉ định cột lưu trữ thông tin về ngôn ngữ cho từng hàng:

Kotlin

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

Java

@Fts4(languageId = "lid")
@Entity(tableName = "users")
public class User {
    // ...

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

Room cung cấp một số tuỳ chọn khác để xác định các thực thể được FTS hỗ trợ, bao gồm thứ tự kết quả, loại bộ mã hoá và bảng được quản lý là nội dung bên ngoài. Để biết thêm thông tin về các tuỳ chọn này, hãy xem tài liệu tham khảo FtsOptions.

Lập chỉ mục các cột cụ thể

Nếu ứng dụng phải hỗ trợ phiên bản SDK mà không cho phép sử dụng các thực thể dựa trên FTS3 hoặc FTS4, thì bạn vẫn có thể lập chỉ mục cho một số cột nhất định trong cơ sở dữ liệu để tăng tốc độ truy vấn. Để thêm chỉ mục vào một thực thể, đưa thuộc tính indices vào trong chú thích @Entity, hãy liệt kê tên của những cột mà bạn muốn đưa vào chỉ mục hoặc chỉ mục tổng hợp. Đoạn mã sau đây minh hoạ quy trình chú thích này:

Kotlin

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

Java

@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;
}

Đôi khi, một số trường hoặc nhóm trường trong cơ sở dữ liệu phải là duy nhất. Bạn có thể thực thi thuộc tính duy nhất này bằng cách đặt thuộc tính unique của chú thích @Index thành true. Mã mẫu sau đây ngăn cản một bảng có hai hàng chứa cùng một tập hợp giá trị cho cột firstNamelastName:

Kotlin

@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?,
    @Ignore var picture: Bitmap?
)

Java

@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;
}

Đưa vào các đối tượng dựa trên AutoValue

Trong Room từ 2.1.0 trở lên, bạn có thể sử dụng các lớp giá trị không thể thay đổi (dựa trên Java), mà nhờ @AutoValue bạn đã chú thích là các thực thể trong cơ sở dữ liệu của ứng dụng. Hỗ trợ này đặc biệt hữu dụng khi hai bản sao của một thực thể được coi là bằng nhau nếu các cột của chúng chứa các giá trị giống nhau.

Khi sử dụng các lớp được chú thích bằng @AutoValue làm thực thể, bạn có thể chú thích các phương thức trừu tượng của lớp bằng cách sử dụng @PrimaryKey, @ColumnInfo, @Embedded@Relation. Tuy nhiên, khi sử dụng các chú thích này, bạn phải thêm chú thích @CopyAnnotations vào mỗi lần để Room có thể diễn giải chính xác các cách triển khai của phương thức được tự động tạo ra.

Đoạn mã sau đây cho thấy ví dụ về một lớp được chú thích bằng @AutoValue được Room thừa nhận là một thực thể:

User.java

@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);
    }
}