일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 리얼하다
- 목적 중심 리더십
- 목적중심리더십
- 좌식테이블
- 재택근무
- T자형인재
- 함수형 프로그래밍
- 테트리스
- 베드테이블
- 베드트레이
- 어떻게 나답게 살 것인가
- 안드로이드
- 브런치작가되기
- 소프시스
- 한달독서
- 한달어스
- 1일1커밋
- 지지않는다는말
- 소프시스 밤부 좌식 엑슬 테이블
- 북한살둘레길
- 아비투스
- 커스텀린트
- 한단어의힘
- 슬기로운 온라인 게임
- 끝말잇기
- 캐치마인드
- 한달브런치북만들기
- 면접
- 프래그먼트
- 자취필수템
- Today
- Total
정상에서 IT를 외치다
[Android, Room] Room One to Many 관계 살펴보기 본문
안녕하세요. 블랙진입니다.
안드로이드 라이브러리 Room에 관한 포스팅을 해보겠습니다. 여기서 주로 다룰 내용은 Room의 One to Many 관계에 대해서 예제 코드와 함께 다뤄 보겠습니다.
Room 이란?
안드로이드 아키텍처 컴포넌트(AAC) 룸 라이브러리는 안드로이드 앱에서 SQLite 데이터베이스를 쉽고 편리하게 사용할 수 있도록 해주는 라이브러리입니다. 간단한 사용법은 이전 저의 포스팅을 확인해 주시면 감사하겠습니다.
One to Many 관계
One to Many 관계를 폴더와 파일을 예시로 작업해 보겠습니다. 여러분도 아시다시피 한 폴더에는 여려개의 파일이 들어갈 수 있습니다.
1. Entity
@Entity(tableName = "folders")
data class FolderEntity(
@PrimaryKey(autoGenerate = true)
val folderId: Int = 0,
val name: String
)
@Entity(tableName = "files")
data class FileEntity(
@PrimaryKey(autoGenerate = true)
val fileId: Int = 0,
val parentFolderId: Int,
val name: String
)
data class FolderAndFiles(
@Embedded val folder: FolderEntity,
@Relation(
parentColumn = "folderId",
entityColumn = "parentFolderId"
)
val files: List<FileEntity>
)
폴더와 파일의 Entity를 각각 생성해 줍니다. 여기서 파일에는 폴더에 대한 정보가 필요하기 때문에 parentFolderId를 추가해 줍니다.
FolderAndFiles는 폴더와 파일의 Entity를 같이 보여주기 위한 클래스 입니다.
@Embedded
Room에서 obejct를 표현하기 위한 어노테이션입니다.
@Relation
부모와 자식 관계를 정의하기 위한 어노테이션입니다.
parentColum에는 부모의 값을, entityColumn에는 자식에서 사용하고 있는 부모의 값을 보여줍니다.
2. Dao
폴더와 관련된 Dao
/**
* Folder
*/
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertFolder(folder: FolderEntity)
@Delete
fun deleteFolder(folder: FolderEntity)
@Query("SELECT * FROM folders ORDER BY folderId DESC") //ASC
fun getFolders(): List<FolderEntity>
@Query("SELECT * FROM folders WHERE name = :name")
fun getFolderByName(name: String): FolderEntity
@Query("DELETE FROM folders WHERE name = :name")
fun deleteFolderByName(name: String)
@Query("DELETE FROM folders")
fun clearFolders()
파일과 관련된 Dao
/**
* File
*/
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertFile(file: FileEntity)
@Delete
fun deleteFile(file: FileEntity)
@Query("SELECT * FROM files")
fun getFiles() : List<FileEntity>
@Query("DELETE FROM files WHERE name = :name")
fun deleteFilerByName(name: String)
@Query("DELETE FROM files")
fun clearFiles()
폴더과 파일의 관계를 보여주는 Dao
/**
* Folder And File
*/
@Transaction
@Query("SELECT * FROM folders ORDER BY folderId DESC") //ASC
fun getFolderAndFilesData() : List<FolderAndFiles>
@Transaction
위 예제의 경우 폴더와 파일을 가져오기 위해 Room에서는 두개의 쿼리문이 돌아갑니다. 이 과정을 자동으로 이뤄지게 하기 위한 어노테이션입니다.
3. 문제 인식
폴더와 파일의 관계가 잘 동작됩니다. 하지만 위 예제 코드에서는 파일을 지우면 그 안에 있는 폴더는 지워지지는 않습니다.
그럼 폴더가 지워졌을 때 파일까지 함께 지워지기 위해서는 어떻게 작업해야 될까요? 수동으로 쿼리문을 동작시켜 주면 되겠지만 저희가 원하는 대답은 이게 아니겠죠! 여기서 ForeignKey를 등록시켜 줌으로써 데이터의 관계를 정의할 수 있습니다.
4. ForeginKey 적용
@Entity(
tableName = "files",
foreignKeys = [
ForeignKey(
entity = FolderEntity::class,
parentColumns = arrayOf("folderId"),
childColumns = arrayOf("parentFolderId"),
onDelete = ForeignKey.CASCADE
)
]
)
data class FileEntity(
@PrimaryKey(autoGenerate = true)
val fileId: Int = 0,
val parentFolderId: Int,
val name: String
)
FileEntity에 위와 같이 ForeignKey를 적용해주면 부모 폴더가 제거되면 그 안에 있던 자식 파일들도 모두 제거할 수 있습니다. 위에서 중요하게 볼 것은 onDelete 속성인데요. onDelete 속성 NO_ACTION, RESETICT, SET_NULL, SET_DEFAUT, CASCADE 값을 적용할 수 있으며 이는 SQLIte에서 사용하던 것과 동일합니다.
여기서 CASCADE를 사용하게 되면 부모가 삭제되거나 수정되게 되면 자식 또한 삭제 혹은 수정되게 됩니다.
5. 부모 폴더 생성
여기서 더 나아가 우리는 이미 알고 있습니다! 폴더 안에 파일만 넣을 수 있는게 아니라 폴더를 넣을 수 있고 그 폴더안에 또 폴더를 넣을 수 있습니다. 폴더안에 폴더를 넣을 수 있는 구조로 코드를 변환해 보겠습니다.
@Entity(tableName = "folders",
foreignKeys = [
ForeignKey(
entity = FolderEntity::class,
parentColumns = arrayOf("folderId"),
childColumns = arrayOf("parentId"),
onDelete = ForeignKey.CASCADE
)])
data class FolderEntity(
@PrimaryKey(autoGenerate = true)
val folderId: Int = 0,
val parentId: Int? = null,
val name: String
)
간단하게 자식 폴더에 부모 폴더의 정보만 추가시켜주면 우리가 알고있는 폴더와 파일 구조를 Room으로 모두 구현할 수 있게 됩니다!
정리
Room의 One to Many 관계에 대한 포스팅은 많이 있습니다. 하지만 좀더 구체적인 예제와 함께 정리하고 싶어 포스팅을 작성하게 되었습니다. 위에서 사용한 예제는 깃허브 링크에서 확인할 수 있습니다.
'안드로이드' 카테고리의 다른 글
[Android, DialogFragment] 커스텀 다이얼로그 프래그먼트 만들기 (0) | 2020.11.18 |
---|---|
[드로이드 나이츠] 2020 드로이드 나이츠 온라인 내용 정리 (0) | 2020.09.27 |
[Android, JavascriptInterface] 웹뷰와 앱간의 통신 예제 (1) | 2020.07.22 |
[Android, MVVM] MVVM 따라하기 - 4 (MVVM 구현) (6) | 2020.06.16 |
[Android, MVVM] MVVM 따라하기 - 3 (RxJava 구현) (2) | 2020.06.09 |