View

RoomDB(2편)

제롱구리 2024. 3. 14. 12:58
728x90

오늘 알아볼 것

저번 시간에 이어서 RoomDB에 대해서 조금 더 알아보려고 한다.


Entiry

'개체'인 entity는 관련이 있는 속성들이 모여 하나의 정보 단위를 말한다.
개체(Entity) 우리가 아는 객체(object)와는 비슷하지만 다른 의미가 있다.
객체는 정보와 동작, 기능 등을 가지고 있지만 개체는 정보 뿐다.

아래 코드는 생성 방법이다.

@Entity(tableName = "UserTable")
data class User (
    var name: String,
    var age: String,
    var phone: String
){
    @PrimaryKey(autoGenerate = true) var id: Int = 0
}

다음과 같이 @Entity라는 어노테이션을 붙여준다. primaryKey는 키 값이기 때문에 유일한(Unique) 값이여야 된다.
autoGenerate를 true 주게 되면 자동으로 값을 생성한다.
(tableName = "테이블이름")을 통해서 테이블 이름을 정해줄 수 있다.


Dao

일종의 Entiry의 행동의 하는 메소들을 말한다고 보면 될거 같다.


아래 코드는 예시 코드이다.

@Dao
interface UserDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insert(user: User)

    @Update
    fun update(user: User)

    @Delete
    fun delete(user: User)

    @Query("SELECT * FROM User") // 테이블의 모든 값을 가져와라
    fun getAll(): List<User>

    @Query("DELETE FROM User WHERE name = :name") // 'name'에 해당하는 유저를 삭제해라
    fun deleteUserByName(name: String)

 //    OnConflictStrategy.ABORT    충돌이 발생할 경우 처리 중단
//    OnConflictStrategy.FAIL    충돌이 발생할 경우 실패처리
//    OnConflictStrategy.IGNORE    충돌이 발생할 경우 무시
//    OnConflictStrategy.REPLACE    충돌이 발생할 경우 덮어쓰기
//    OnConflictStrategy.ROLLBACK    충돌이 발생할 경우 이전으로 되돌리기

}

위에 예제코드를 보는것과 같이 @Insert, @Update 등의 간단한 어노테이션을 이용한 추가,업데이트, 삭제 등을 할 수도 있고
@Query를 이용하여 직접 코드를 사용해 짤 수도 있다.(이부분이...너무 힘들다.)
여기서 한가지 주의 해야될 부분이 있다.

바로 @Insert옆의 코드부분이다. 저것이 무엇일까?
RoomDB의 경우에는 우리가 일반적으로 사용하는 Data클래스와 조금 다른 부분이 있다. 그 부분은 바로 PrimaryKey 부분이다.
물론 우리가 api로 데이터를 받을까 PrimaryKey 부분이 다 처리 되어서 들어오기는 하지만 우리가 DB를 관리하게 되면 해당 부분을 우리가 조금 신경써야되기 때문이다.

즉 Primarkey 값은 유일한 값으로 중복 되어서는 안된다. 그렇기 때문에 만약 우리가 중복된 데이터를 받게 되면 충돌이 일어나 문제가 생기게된다. 그부분을 저 코드 부분으로 처리할 수 있는 것이다.
(캬~~ 좋넹...좋아...실제로 좋음, 없어어봐 자네들이 다 처리해야된다고 Query로....끔찍하지? 누구는가 우는거 같긴하지만..)


Room Database

Room Database는 데이터 베이스를 생성하고 관리하는 객체를 만들기 위한 추상 클래스이다.
RoomDatabase 클래슬 상속 받고, @Database라는 어노테이션으로 표시해준다.(너가 바로 Database!!)
아래 코드는 예제 코드이다.

//데이터 베이스 한개가 Entity를 한개 가질 때
@Database(entities = [User::class], version = 1)
abstract class UserDatabase: RoomDatabase() {
    abstract fun userDao(): UserDao
}

//데이터 베이스 한개가 Entity를 여러개 가질 때
@Database(entities = arrayOf(User::class, Student::class), version = 1)
abstract class UserDatabase: RoomDatabase() {
    abstract fun userDao(): UserDao
}

위 코드를 보면 2개의 데이터 베이스가 있다. 실제 코드에서 이런 경우는 없겠지만 설명을 위해서 넣었다.
@Database 어노테이션의 옆 코드 부분을 보면 (entities = [User::class], version = 1) 이라고 되어 있는데
entities에는 위에서 배운 entity를 넣어주는 부분이고, version은 entity의 구조를 변경해야 하는 일이 생겼을 때
이전 구조와 현재 구조를 구분해 준다.
구조가 바뀌었는데 version에 같은 값을 넣어주게 되면 붉은색 error라는 친구가 당신을 반겨 줄 것이다.

위 코드 중에 아래에 있는 Database는 한개의 데이터 베이스가 여러개의 Entity를 가질 때이다.



[ 이제는 실제로 사용하는 부분이다. ]

일단 데이터 베이스 객체를 인스턴스 할 때 싱글턴을 권장하고 있다.
왜냐면 비용이..많이 든다.(이래도 모르겠다고? 개인 컴퓨터 하드나 ssd를 저장할때마다 구매해야 된다고 생각하면 얼마들지...)
아래 예제 코드는 싱글톤이다.

@Database(entities = [User::class], version = 1)
abstract class UserDatabase: RoomDatabase() {
    abstract fun userDao(): UserDao

    companion object {
        private var instance: UserDatabase? = null

        @Synchronized
        fun getInstance(context: Context): UserDatabase? {
            if (instance == null) {
                synchronized(UserDatabase::class){
                    instance = Room.databaseBuilder(
                        context.applicationContext,
                        UserDatabase::class.java,
                        "user-database"
                    ).build()
                }
            }
            return instance
        }
    }
}

databaseBuilder라는 static 메서드를 사용하고 context와 database 클래스 우리가 사용할 데이터베이스의 이름을 넘경주면 된다.
그리고 만약에 싱글톤이 싫다(난 하드 저장할때 마다 사겠다!)라고 하면 companion object 부분을 호출부분에 사용하면된다.

아래 코드는 "싱글턴" 사용 부분과 난 "싱글턴이 싫다" 사용부분이다.


        var newUser = User("제롱이", "100쌀", "010-1111-2222")

        // 싱글톤 패턴을 사용하지 않은 경우
        val db = Room.databaseBuilder(
                applicationContext,
                AppDatabase::class.java,
                "user-database"
        ).build()
        db.UserDao().insert(newUser)

        // 싱글톤 패턴을 사용한 경우
        val db = UserDatabase.getInstance(applicationContext)
        db!!.userDao().insert(newUser)



이렇게 간단히 알아봤다
추후에 직접 hilt와 같이 사용한 코드를 가지고 다루보겠다. 성공하면...
(이것때문에...몇일을 못잤는데 아직도 하는중....)

'TIL > 스터디' 카테고리의 다른 글

안드로이드 단일 아키텍처  (0) 2024.03.19
ViewBinding  (0) 2024.03.18
RoomDB  (0) 2024.03.14
코루틴-2(Coroutine)  (0) 2024.03.07
코루틴-1(Coroutine)  (0) 2024.03.06
Share Link
reply
«   2024/12   »
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
29 30 31