-
Room 을 사용할 때 entity 들을 정의하게 된다.
각각의 entity 는 Database 의 table 에 매칭된다.
Database class 에 entities array 로 제공하면 자동으로 생성된다.
-
@Entity
data class User(@PrimaryKey var id:Int, var firstName:String?, var lastName:String?)
-
field 를 public 으로 만들거나, getter, setter 를 제공해주면 된다.
getter, setter 를 사용할 경우, JavaBeans convention 을 따른다는 것을 알고 써야 한다.
-
Entity 는 empty constructor 를 가질 수도 있고, entity 의 field 들을 가질 수도 있다.
또한 full, partial constructor 도 가질 수 있다. (partial 은 일부 field 만 가지고 있는 경우)
Use a primary key
-
각각의 entity 는 적어도 한개의 primary key 를 정의해야 한다.
한개의 field 만 있다고 해도, 그 녀석을 @PrimaryKey annotate 해야 한다.
automatic ID 를 지정하고 싶다면, @PrimaryKey 에 autoGenerate property 를 지정하면 된다.
composite primary key 를 가져야 한다면, @Entity 에 primaryKeys property 를 지정하면 된다.
@Entity(primaryKeys = arrayof("firstName", "lastName"))
data class User(
val firstName:String?
val lastName:String?
)
-
기본적으로 Room 은 database table name 으로 class name 을 그대로 사용한다.
만약 table 이 이름을 다르게 가져갔으면 한다면, @Entity 에 tableName property 를 지정해주면 된다.
@Entity(tableName = "users")
data class User(
// …
)
-
참고로 SQLite 의 table name 은 case-insensitive 하다.
-
Room 은 field name 을 column name 으로 사용한다.
만약 다른 이름을 사용하게 하고 싶다면, @ColumnInfo annotation 을 field 에 사용해주면 된다.
@Entity(tableName = "users")
data class User(
@PrimaryKey val id:Int,
@ColumnInfo(name = "first_name") val firstName:String?,
@ColumnInfo(name = "last_name") val lastName:String?
)
Ignore fields
-
기본적으로 Room 은 entity 에 정의된 모든 field 에 대해 column 을 생성한다.
만약 entity 가 가진 field 중에 column 으로 만들고 싶지 않은 것이 있다면, @Ignore annotation 을 넣어주면 된다.
@Entity
data class User(
@PrimaryKey val id:Int,
val firstName:String?,
val lastName:String?,
@Ignore val picture:Bitmap?
)
-
entity 가 parent entity 를 가질 경우, @Entity 의 ignoreColumns property 를 사용하는 것이 더 쉽다.
open class User{
var picture:Bitmap? = null
}
@Entity(ignoreColumns = arrayOf("picture"))
data class RemoteUser(
@PrimaryKey val id:Int,
val hasVpn:Boolean
): User()
Provide table search support
-
Room 은 annotation 을 통해 db table 의 상세정보를 검색할 수 있는 쉬운 방법을 제공한다.
app 의 minSdkVersion 이 16(JB) 이상이면, full-text search 를 할 수 있다.
* Support full-text search
-
앱이 db 안의 정보를 full-text search(FTS) 를 통해 빠르게 접근하고자 한다면, entity 들이 FTS3, FTS4 SQLite extension module 을 사용하는 virtual table 을 갖도록 하면 된다.
이 기능을 사용하기 위해서는 Room 2.1.0 이상이어야 하며, @Fts3 또는 @Fts4 annotation 을 해당 entity 에 주면 된다.
// 오래된 SQLite version 과 호환되기 위해서나, disk 용량이 적다면 Fts3 을 쓰는 것이 좋다.
@Fts4
@Entity(tableName = "users")
data class User(
// FTS-table-backed entity 를 위해 primary key 를 지정하는 것은 optional 이다. 그러나 지정한다면, 이 type 과 column name 을 사용해야 한다.
@PrimaryKey @ColumnInfo(name = "rowId") val id:Int,
@ColumnInfo(name = "first_name") val firstName:String?
)
-
FTS-enabled table 은 항상 primary key 를 INTEGER type 으로 사용한다. 그리고 그 이름은 rowId 가 된다.
FTS-table-backed entity 가 primary key 를 정의한다면, 반드시 해당 type 과 column name 을 써야 한다.
-
table 이 여러개의 언어를 지원한다면, languageId option 을 column 에 주어서 각각의 row 에 언어 정보를 넣을 수 있다.
@Fts4(languageId = "lid")
@Entity(tableName = "users")
data class User(
@ColumnInfo(name = "lid") val languageId:Int
)
-
Room 은 FTS-backed entity 정의를 위한 다른 option 들도 제공한다. result ordering, tokenizer type, 외부 컨텐츠로 관리되는 table 들이 그 예이다.
-
돼왕 참고사항 (https://developer.android.com/reference/androidx/room/Fts3)
FTS3 와 FTS4 는 SQLIte virtual table module 로, 문서들에서 full-text search 를 할 수 있도록 도와준다.
FTS entity table 은 항상 rowid 라는 이름의 column 을 가져야 하며, 이 녀석은 INTEGER PRIMARY KEY 이며 index 이다.
다시 말해 FTS entity 는 PrimaryKey 로 annotate 된 하나의 필드만 가질 수 있으며, 이것의 이름은 rowid 여야 하고, INTEGER 타입이어야 한다.
해당 필드는 클래스에서 생략될 수 있지만, 그래도 query 에서는 계속 사용된다.
FTS entity 의 rowid 를 제외한 모든 필드는 TEXT type 이다.
* Index specific columns
-
앱이 FTS3 이나 FTS4-table-backed entity 를 사용하는 것을 지원하지 않는 SDK version 을 지원해야 한다면, query 속도 향상을 위해 index 를 사용할 수 있다.
entity 에 index 를 추가하기 위해서는 @Entity 에 indices property 를 통해 index 또는 composite index 로 만들고 싶은 column name 을 전달해주면 된다.
@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?
)
-
종종 몇몇 field 또는 field group 은 db 에서 unique 해야만 한다.
이 unique 성을 @Index annotation 의 unique property 를 true 로 줌으로써 구현할 수 있다.
@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?
)
Include AutoValue-based objects
-
이 기능은 Java-based entity 에서만 사용할 수 있는 기능이다.
이 기능을 kotlin 기반에서 똑같이 구현하려면 data class 를 쓰는 것이 좋다.
-
Room 2.1.0 이상에서 Java-based immutable value class 를 만들 수 있으며, 이는 @AutoValue 라는 annotation 을 사용하면 된다.
이 기능은 2개의 entity instance 들의 column 들이 같은 값을 가지고 있을 때, 해당 entity 들이 같은 녀석이라고 판단할 때 좋다.
-
@AutoValue 로 annotate 된 class 들을 사용할 때, @PrimaryKey, @ColumnInfo, @Embedded, @Relation 등을 이용하여 class 의 abstract method 들을 annotate 해야 한다.
이 annotation 들을 사용할 때 반드시 @CopyAnnotations 을 매번 지정해서, Room 이 auto-generated implementation 을 제대로 해석할 수 있게 도와줘야 한다.
@AutoValue
@Entity
public abstract class User{
@CopyAnnotations // 이 녀석을 안 써주면, auto-generated 된 table 에서 @PrimaryKey 정보가 사라진다.
@PrimaryKey
public abstract long getId();
public abstract String getFirstName();
public abstract String getLastName();
// Room 이 User object 를 만들기 위해서 factory method 를 사용한다.
public static User create(long id, String firstName, String lastName){
return new AutoValue_User(id, firstName, lastName);
}
}
-
돼왕 참고사항
@AutoValue 가 자동으로 hashCode(), equals(), toString() 함수를 만들어준다.
자동으로 생성된 class 이름은 AutoValue_OriginalClassName 이 된다.
그러나 외부에서 사용하는 이름은 OriginalClassName 그대로 사용하면 된다.
-
참고자료
https://developer.android.com/training/data-storage/room/defining-data
'프로그래밍 놀이터 > 안드로이드, Java' 카테고리의 다른 글
[android] WorkManager 를 사용해보자 (0) | 2020.08.21 |
---|---|
[android] MultiDex 에 대한 이야기 (0) | 2020.08.20 |
[android] Accessing data using Room DAOs - Room 에 대해 알아보자 (0) | 2020.08.18 |
[android] 기초 - Room 에 대해 알아보자 (0) | 2020.08.17 |
[android] dpi 값이 바뀔 수 있구나?!! ㄷㄷㄷ (0) | 2020.08.15 |
댓글