Room 항목을 사용하여 데이터 정의

Room 지속성 라이브러리를 사용하여 앱 데이터를 저장할 때는 저장하려는 객체를 나타내는 항목을 정의해야 합니다. 각 항목은 연결된 Room 데이터베이스의 테이블에 상응하고, 항목의 각 인스턴스는 상응하는 테이블의 데이터 행 하나를 나타냅니다.

즉, SQL 코드를 작성하지 않고도 Room 항목을 사용하여 데이터베이스 스키마를 정의할 수 있습니다.

항목 분석

각 Room 항목을 @Entity 주석이 달린 클래스로 정의합니다. Room 항목에는 기본 키를 구성하는 하나 이상의 열을 비롯하여 데이터베이스의 상응하는 테이블에 있는 각 열의 필드가 포함되어 있습니다.

다음 코드는 ID, 이름, 성 열이 포함된 User 테이블을 정의하는 간단한 항목의 예입니다.

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

기본적으로 Room은 클래스 이름을 데이터베이스 테이블 이름으로 사용합니다. 테이블 이름을 다르게 하려면 @Entity 주석의 tableName 속성을 설정하세요. 마찬가지로 Room은 기본적으로 필드 이름을 데이터베이스의 열 이름으로 사용합니다. 열 이름을 다르게 하려면 @ColumnInfo 주석을 필드에 추가하고 name 속성을 설정하세요. 다음 예는 테이블과 열의 맞춤 이름을 보여줍니다.

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

기본 키 정의

각 Room 항목은 상응하는 데이터베이스 테이블의 각 행을 고유하게 식별하는 기본 키를 정의해야 합니다. 가장 간단한 방법은 단일 열에 @PrimaryKey로 주석을 다는 것입니다.

Kotlin

@PrimaryKey val id: Int

Java

@PrimaryKey
public int id;

복합 기본 키 정의

항목 인스턴스가 여러 열의 조합으로 고유하게 식별되도록 하려면 이러한 열을 @EntityprimaryKeys 속성에 나열하여 복합 기본 키를 정의하면 됩니다.

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

필드 무시

기본적으로 Room은 항목에 정의된 각 필드의 열을 생성합니다. 항목의 필드를 유지하지 않으려면 다음 코드 스니펫과 같이 @Ignore를 사용하여 필드에 주석을 달면 됩니다.

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

항목이 상위 항목에서 필드를 상속하는 경우 일반적으로 @Entity 속성의 ignoredColumns 속성을 사용하는 것이 더 쉽습니다.

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은 데이터베이스 테이블에서 세부정보를 더 쉽게 검색할 수 있게 하는 여러 유형의 주석을 지원합니다. 앱의 minSdkVersion이 16 이상이라면 전체 텍스트 검색을 사용하세요.

전체 텍스트 검색 지원

앱에서 FTS(전체 텍스트 검색)를 통해 데이터베이스 정보에 매우 빠르게 액세스해야 한다면 FTS3 또는 FTS4 SQLite 확장 모듈을 사용하는 가상 테이블로 항목을 지원하세요. Room 2.1.0 이상에서 제공되는 이 기능을 사용하려면 다음 코드 스니펫과 같이 지정된 항목에 @Fts3 또는 @Fts4 주석을 추가하면 됩니다.

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

테이블이 여러 언어로 된 콘텐츠를 지원하는 경우 다음과 같이 languageId 옵션을 사용하여 각 행의 언어 정보를 저장하는 열을 지정하세요.

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은 결과 정렬, tokenizer 유형, 외부 콘텐츠로 관리되는 테이블 등 FTS 지원 항목을 정의하기 위한 몇 가지 기타 옵션을 제공합니다. 이러한 옵션에 관한 자세한 내용은 FtsOptions 참조를 확인하세요.

특정 열 색인 생성

앱에서 FTS3 또는 FTS4 테이블 지원 항목을 지원하지 않는 SDK 버전을 지원해야 하는 경우에도 데이터베이스에 있는 특정 열의 색인을 생성하여 쿼리 속도를 높일 수 있습니다. 항목에 색인을 추가하려면 @Entity 주석 내에 indices 속성을 포함하여 색인 또는 복합 색인에 포함하려는 열의 이름을 나열합니다. 다음 코드 스니펫은 이 주석 달기 프로세스를 보여줍니다.

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

데이터베이스의 특정 필드 또는 필드 그룹이 고유해야 하는 경우도 있습니다. @Index 주석의 unique 속성을 true로 설정하여 고유성 속성을 적용할 수 있습니다. 다음 코드 샘플은 firstNamelastName 열의 값 세트가 동일한 행이 한 테이블에 1개만 있도록 합니다.

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

AutoValue 기반 객체 포함

Room 2.1.0 이상에서는 Java 기반의 변경할 수 없는 값 클래스@AutoValue로 주석을 달아 앱 데이터베이스의 항목으로 사용할 수 있습니다. 이 기능은 열에 동일한 값이 포함되면 항목의 두 인스턴스가 동일한 것으로 간주될 때 특히 유용합니다.

@AutoValue 주석이 달린 클래스를 항목으로 사용할 때 @PrimaryKey, @ColumnInfo, @Embedded, @Relation을 사용하여 클래스의 추상 메서드에 주석을 달 수 있습니다. 그러나 이러한 주석을 사용할 경우 Room이 자동 생성된 메서드 구현을 올바르게 해석할 수 있도록 매번 @CopyAnnotations 주석을 포함해야 합니다.

다음 코드 스니펫은 Room이 항목으로 인식하는 @AutoValue 주석이 달린 클래스의 예를 보여줍니다.

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