RoodDB

yugyeongKim·2022년 11월 25일
0

안드로이드

목록 보기
12/13

1. Gradle 추가

안드로이드 roomDB 페이지

위의 페이지에서 가져와서 빌드에 붙인다.

dependencies {
    ...
    implementation("androidx.room:room-runtime:2.4.3")
    annotationProcessor("androidx.room:room-compiler:2.4.3")
    // To use Kotlin annotation processing tool (kapt)
    kapt("androidx.room:room-compiler:2.4.3")
    ...
}

// To use Kotlin annotation processing tool (kapt)
kapt("androidx.room:room-compiler:roomversion")//TouseKotlinSymbolProcessing(KSP)ksp("androidx.room:roomcompiler:room_version") // To use Kotlin Symbol Processing (KSP) ksp("androidx.room:room-compiler:room_version")

이거 둘 중 하나만 해야한다.

plugins {
    ...
    id 'kotlin-kapt'
}

그리고 맨위에 plusins{}안에 id 'kotlin-kapt'를 작성하지 않으면 싱크가 안된다고 하니 꼭 작성한다.

2. Entity 생성

  • Memo.kt
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity
data class Memo(
    @ColumnInfo(name = "content") val content: String,
    @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "memoId") val memoId: Int = 0
)

autoGenerate = true
: Room에서 항목 인스턴스에 자동 ID를 할당하게 해준다.

3. Dao 생성

  • MemoDao.kt
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query

@Dao
//데이터 생성, 삽입, 수정 하는 내용을 작성
interface MemoDao {
    //삽입
    @Insert
    fun insert(memo: Memo)
    //삭제
    @Delete
    fun delete(memo: Memo)
//    모두 선택
    @Query("SELECT * FROM Memo")
    fun selectAll(): List<Memo>
    //id로 선택
    @Query("SELECT * FROM Memo WHERE memoId =:memoId")
    fun selectByUserId(memoId: Int): Memo
    //이름으로 선택
    @Query("SELECT * FROM Memo WHERE content =:content")
    fun selectByUserContent(content: String): List<Memo>
    //수정
    @Query("UPDATE Memo SET content= :content WHERE memoId =:memoId")
    fun updateContentByUserId(memoId: Int, content: String)
}

select를 사용했기 때문에 return타입을 적어줘야 한다.

4. Room Database 클래스, DB 객체 생성

  • Database
@Database(entities = [User::class], version=1)
abstract class AppDatabase: RoomDatabase() {

version: 데이터베이스의 구조가 바뀌었을 때 그걸 version으로 구분. 중간에 바꾸면 꼭 version을 바꿔야 한다.

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

RoomDatabase를 상속받았기 때문에 알아서 밑에 값들을 채워준다.

getInstance함수로 룸데이터베이스를 가져온다.

  • AppDatabase.kt
package com.example.memo

import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase


@Database(entities = [Memo::class], version=1)
abstract class AppDatabase: RoomDatabase() {
    abstract  fun MemoDao(): MemoDao
    //전역적으로 사용하는 것을 담음
    companion object {
        //실제 데이터베이스가 담기는 변수
        private  var appDatabase:AppDatabase? = null

        //이 어노테이션을 작성해주는 이유: 공유자원의 문제, 여러쓰레드에서 동시에 하나에
        //자원에 접근하려 할 때 그런거를 방지하기 위해 작성해줌
        @Synchronized
        fun getInstance(context: Context): AppDatabase? {
            if(appDatabase == null) {
                synchronized(AppDatabase::class.java) {
                    appDatabase = Room.databaseBuilder(
                        context.applicationContext,
                        AppDatabase::class.java,
                        //룸디비를 만드는 데이터베이스마다 반드시 다른 이름으로 해줘야함
                        "app-database"
                    ).allowMainThreadQueries().build()
                }
            }
            return appDatabase
        }
    }
}

entities = [Memo::class]
: 여러 클래스가 들어갈 수 있기 때문에 배열로 작성
중간에 데이터베이스를 바꾸면 version을 꼭 바꿔야 한다...

데이터 베이스 버전 오류

Caused by: java.lang.IllegalStateException: Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number. You can simply fix this by increasing the version number.

데이터베이스 버전을 바꿔야 하는듯 하다. 근데 몇으로바꿔야하노...?

A migration from 1 to 2 was required but not found. Please provide the necessary Migration path via RoomDatabase.Builder.addMigration(Migration ...)
2로 변경을 하니까 이런 새로운 오류가 뜬다............

roodb 데이터 변경시 해야할거 공식문서
이거대로 테이블이름 변경했다고 적었는데 또 오류가 떴다.

error: Schema export directory is not provided to the annotation processor so we cannot import the schema. To generate auto migrations, you must provide room.schemaLocation annotation processor argument AND set exportSchema to true.

스택오버플로우

defaultConfig {
...
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = ["room.schemaLocation":
                                     "$projectDir/schemas".toString()]
            }
        }
}

이렇게 하고나면
A migration from 1 to 2 was required but not found. Please provide the necessary Migration path via RoomDatabase.Builder.addMigration(Migration ...) or allow for destructive migrations via one of the RoomDatabase.Builder.fallbackToDestructiveMigration* methods.
이제는 이런 오류가 뜬다🤦‍♀️.......

둘중하나를 해주면 되겠지?

  • AppDatabase.kt
@Database(entities = [Memo::class], version=2, exportSchema = true)
abstract class AppDatabase: RoomDatabase() {
    @RenameTable(fromTableName = "User", toTableName = "Memo")
    class MyAutoMigration : AutoMigrationSpec
//    abstract fun userDao(): UserDao
    abstract  fun MemoDao(): MemoDao
    //전역적으로 사용하는 것을 담음
    companion object {
        //실제 데이터베이스가 담기는 변수
        private  var appDatabase:AppDatabase? = null

        val MIGRATION_1_2 = object : Migration(1, 2) {
            override fun migrate(database: SupportSQLiteDatabase) {
                database.execSQL("CREATE TABLE `Memo` (`content` TEXT, " +
                        "PRIMARY KEY(`id`))")
            }
        }
        @Synchronized
        fun getInstance(context: Context): AppDatabase? {}
    }
}

이렇게 수동으로 바꾸면 잘작동한다.

0개의 댓글