[Jetpack] Room 프레임워크를 사용하여 Android 플랫폼에서 SQLite 데이터베이스에 액세스(종속성 가져오기 | Entity 엔터티 클래스 정의 | Dao 데이터베이스 액세스 객체 인터페이스 정의 | 데이터베이스 인스턴스 클래스 정의)





1. Room 프레임워크 사용의 핵심 포인트




1. build.gradle 빌드 스크립트 구성 지침


Room 프레임워크경우 Java 언어 와 Kotlin 언어를 사용한 개발을 위해 build.gradle 빌드 스크립트 에서 서로 다른 구성을 만들어야 하며 주로 다음 두 가지 구성이 있습니다.

  • 다른 플러그인이 적용됩니다.
  • 종속 라이브러리를 가져오는 다양한 방법

애플리케이션 플러그인

적용된 플러그인 차이점:

  • Java 언어를 사용하여 개발하는 경우 Android 플러그인 만 가져오면 됩니다 .
plugins {
    
    
    id 'com.android.application'
}
  • Kotlin 언어 개발을 사용하는 경우 Android 플러그인을 기반으로 kotlin 및 kotlin-kapt 플러그인을 추가로 가져와야 합니다 .
plugins {
    
    
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    id 'kotlin-kapt'
}

의존성 가져오기

종속 라이브러리 가져오기의 차이점: 가져오기가 잘못되면 표시됨

  • Java 언어 개발을 사용하는 경우 annotationProcessor를 사용하여 주석 프로세서를 가져와서 컴파일 중에 코드를 생성 해야 합니다 .
    // 导入 Room 依赖库
    implementation 'androidx.room:room-runtime:2.2.5'
    // 导入注解处理器 ( Java )
    annotationProcessor 'androidx.room:room-compiler:2.2.5'
  • Kotlin 언어 개발을 사용하는 경우 컴파일 중에 코드를 생성하려면 kapt를 사용하여 주석 프로세서를 가져와야 합니다 .
    // 导入 Room 依赖库
    implementation 'androidx.room:room-runtime:2.2.5'
    // 导入注解处理器 ( Kotlin )
    kapt 'androidx.room:room-compiler:2.2.5'

2. 엔터티 엔터티 클래스 정의


Room 프레임워크를 사용하는 애플리케이션에서 Entity 엔터티 클래스는 데이터베이스 테이블에 해당하며 , Entity 엔터티 클래스가 정의된 후에는 데이터베이스 정의되었음을 의미합니다.


@Entity 주석

Entity 엔터티 클래스 데이터베이스 테이블의 이름을 정의하는 데 사용되는 tableName 매개 변수에 전달될 수 있는 @Entity 주석으로 수정해야 합니다.

@Entity(tableName = "student")
class Student {
    
    
}

@PrimaryKey 주석

기본 키를 정의하고 @PrimaryKey 주석을 사용하여 기본 키를 수정하고 autoGenerate = true 매개변수를 설정하여 기본 키가 자동 증가되도록 합니다.

데이터베이스 테이블 열 정보는 @ColumnInfo 주석을 사용하여 정의되며 이 주석의 매개변수는 다음과 같습니다.

  • name = "id"는 데이터 테이블의 열 이름을 정의합니다 .
  • typeAffinity = ColumnInfo.INTEGER는 필드 유형이 int 정수임을 정의합니다 .
    /**
     * @PrimaryKey 设置主键 autoGenerate 为自增
     * @ColumnInfo name 设置列名称 / typeAffinity 设置列类型
     */
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "id", typeAffinity = ColumnInfo.INTEGER)
    var id: Int = 0

@ColumnInfo 주석

일반 필드를 정의하려면 주석을 사용하여 필드를 수정 하기 하면 됩니다 .데이터베이스 테이블 이름을 설정하고 열 유형을 문자열 유형으로 설정하십시오.@ColumnInfoname = "name"typeAffinity = ColumnInfo.TEXT

    /**
     * 姓名字段
     * 数据库表中的列名为 name
     * 数据库表中的类型为 TEXT 文本类型
     */
    @ColumnInfo(name = "name", typeAffinity = ColumnInfo.TEXT)
    lateinit var name: String

@주석 무시

수정된 필드

일부 필드가 데이터베이스 테이블 열로 설정될 필요가 없는 경우 비즈니스 로직에서만 사용되며 데이터베이스에 삽입할 필요가 없으며 필드를 수정하는 데만 사용하십시오 .@Ignore

    /**
     * 有些属性用于做业务逻辑
     * 不需要插入到数据库中
     * 使用 @Ignore 注解修饰该属性字段
     */
    @Ignore
    lateinit var studentInfo: String

수정자 기능

@Ignore 주석을 사용하여 생성자를 표시한 후 Room 프레임워크는 생성자를 사용하지 않습니다.

다음 세 가지 생성자 중

  • Room 프레임워크는constructor(id: Int, name: String, age: Int) 생성자를 사용합니다 .
  • 개발자 constructor(name: String, age: Int)constructor(id: Int)생성자를 사용합니다.
    /**
     * 默认的构造方法给 Room 框架使用
     */
    constructor(id: Int, name: String, age: Int) {
    
    
        this.id = id
        this.name = name
        this.age = age
    }

    /**
     * 使用 @Ignore 注解标注构造函数后
     * Room 就不会使用该构造方法了
     * 这个构造方法是给开发者使用的
     */
    @Ignore
    constructor(name: String, age: Int) {
    
    
        this.name = name
        this.age = age
    }

    /**
     * 使用 @Ignore 标签标注后
     * Room 就不会使用该构造方法了
     * 这个构造方法是给开发者使用的
     */
    @Ignore
    constructor(id: Int) {
    
    
        this.id = id
    }

3. Dao 데이터베이스 액세스 개체 인터페이스 정의


@Dao 주석

정의된 Dao 데이터베이스 액세스 개체 인터페이스는 @Dao 주석으로 수정된 인터페이스 인터페이스입니다 .

/**
 * 数据库访问对象接口 / 使用 @Dao 注解修饰
 * 提供数据库的增删改查方法
 */
@Dao
interface StudentDao {
    
    

@삽입 주석

데이터베이스에 데이터를 삽입하려면 @Insert 주석을 사용하여 해당 추상 메소드를 수정하십시오.

    /**
     * 向数据库表中插入元素
     */
    @Insert
    fun insert(student: Student)

@삭제 주석

데이터베이스에서 데이터를 삭제하려면 @Delete 주석을 사용하여 해당 추상 메소드를 수정하십시오.

    /**
     * 从数据库表中删除元素
     */
    @Delete
    fun delete(student: Student)

@업데이트 주석

데이터베이스의 데이터를 업데이트하려면 @Update 주석을 사용하여 해당 추상 메소드를 수정하십시오.

    /**
     * 修改数据库表元素
     */
    @Update
    fun update(student: Student)

@Query 주석

데이터베이스의 데이터를 쿼리하려면 @Query 주석을 사용하여 해당 추상 메서드를 수정합니다.

문자열 매개변수는 쿼리의 SQL 문인 주석 에 설정할 수 있으며 들어오는 매개변수는 콜론을 사용하여 액세스 할 수 있습니다 .:

    /**
     * 查询数据库表
     */
    @Query("select * from student")
    fun query(): List<Student>

    /**
     * 根据传入的 id 查询数据库表
     * 在注解中使用 :id 调用参数中的 id: Int
     */
    @Query("select * from student where id = :id")
    fun query(id: Int): List<Student>

4. RoomDatabase 데이터베이스 인스턴스 클래스 정의


정의된 RoomDatabase 데이터베이스 인스턴스 클래스는 RoomDatabase 추상 클래스를 상속 하고 동시에 주석 하는 추상 클래스입니다 .@Database

@Database(entities = [Student::class], version = 1, exportSchema = false)
abstract class StudentDatabase: RoomDatabase() {
    
    

이 추상 클래스에서 추상 메서드를 정의하여 데이터베이스 액세스 객체를 얻습니다.

    /**
     * 获取 数据库访问 对象
     * 这是必须要实现的函数
     */
    abstract fun studentDao(): StudentDao

이 클래스를 싱글톤 클래스로 설정하고 싱글톤 클래스 개체가 초기화될 때 데이터베이스를 만듭니다 .

    companion object {
    
    
        lateinit var instance: StudentDatabase

        fun inst(context: Context): StudentDatabase {
    
    
            if (!::instance.isInitialized) {
    
    
                synchronized(StudentDatabase::class) {
    
    
                    // 创建数据库
                    instance = Room.databaseBuilder(
                        context.applicationContext,
                        StudentDatabase::class.java,
                        "student_database.db")
                        .allowMainThreadQueries() // Room 原则上不允许在主线程操作数据库
                                                  // 如果要在主线程操作数据库需要调用该函数
                        .build()
                }
            }
            return instance;
        }
    }

데이터베이스 코드를 초기화합니다.

  • 먼저 Room.databaseBuilder 함수를 호출하고 RoomDatabase.Builder 개체를 만들고 Context 컨텍스트, StudentDatabase 클래스 개체 및 데이터베이스 이름과 같은 매개 변수를 전달합니다.
  • 그런 다음 RoomDatabase.Builder 개체의 빌드 함수를 호출하여 데이터베이스를 만듭니다.
  • 참고: Room은 원칙적으로 메인 스레드에서 데이터베이스 작업을 허용하지 않습니다. 메인 스레드에서 데이터베이스를 운영 하려면 RoomDatabase.Builder # allowMainThreadQueries 함수를 호출하여 메인 스레드 작업을 허용해야 합니다.
                    // 创建数据库
                    instance = Room.databaseBuilder(
                        context.applicationContext,
                        StudentDatabase::class.java,
                        "student_database.db")
                        .allowMainThreadQueries() // Room 原则上不允许在主线程操作数据库
                                                  // 如果要在主线程操作数据库需要调用该函数
                        .build()

5. Room 프레임워크를 호출하여 데이터베이스에 액세스


먼저 RoomDatabase 데이터베이스 인스턴스 클래스를 얻고 싱글톤 획득 함수를 호출한 다음 이 함수를 호출하여 해당 데이터베이스를 생성합니다.

        // 获取 StudentDatabase
        var studentDatabase: StudentDatabase = StudentDatabase.inst(this)

그런 다음 데이터베이스 액세스 객체 Dao를 획득 하고 RoomDatabase 데이터베이스 인스턴스 클래스의 추상 메서드를 통해 획득합니다.

        // 获取数据库访问对象
        var studentDao: StudentDao = studentDatabase.studentDao()

마지막으로 Dao 데이터베이스 액세스 개체를 사용하여 데이터베이스 액세스 작업을 수행하고 스레드에서 데이터베이스에 액세스하는 것이 좋습니다.

        thread(start = true) {
    
    
            // 插入数据
            var s1 = Student("Tom", 18)
            var s2 = Student("Jerry", 16)
            studentDao.insert(s1)
            studentDao.insert(s2)

            // 查询数据
            var students = studentDao.query()
            Log.i("MainActivity", "数据库查询结果 ( 插入后首次查询 ) : " + students)

            // 更新数据 , 将学生年龄都设置为 20
            for (i in 0.. students.size - 1) {
    
    
                students[i].age = 20
                studentDao.update(students[i])
            }
            students = studentDao.query()
            Log.i("MainActivity", "数据库查询结果 ( 修改后查询结果 ) : " + students)

            // 删除数据
            var s_delete = Student(1)   // 删除的元素只需要传入 id 即可
            studentDao.delete(s_delete)
            students = studentDao.query()
            Log.i("MainActivity", "数据库查询结果 ( 删除后查询结果 ) : " + students)
        }




2. 전체 코드 예제




1. build.gradle 빌드 스크립트


build.gradle 빌드 스크립트에서는 주로 Kotlin 플러그인 과 Kotlin 주석 플러그인을 가져옵니다.

Java 언어를 사용하여 개발하는 경우 이 두 플러그인을 가져올 필요가 없습니다.

    id 'org.jetbrains.kotlin.android'
    id 'kotlin-kapt'

컴파일 타임에 코드를 생성하는 Room 종속성 라이브러리 및 주석 프로세서를 가져옵니다 .

    // 导入 Room 依赖库
    implementation 'androidx.room:room-runtime:2.2.5'
    // 导入注解处理器 ( Kotlin )
    kapt 'androidx.room:room-compiler:2.2.5'
    // 导入注解处理器 ( Java )
    //annotationProcessor 'androidx.room:room-compiler:2.2.5'

전체 코드는 다음과 같습니다.

plugins {
    
    
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    id 'kotlin-kapt'
}

android {
    
    
    namespace 'kim.hsl.roomdemo'
    compileSdk 32

    defaultConfig {
    
    
        applicationId "kim.hsl.roomdemo"
        minSdk 21
        targetSdk 32
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
    
    
        release {
    
    
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
    
    
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
    
    
        jvmTarget = '1.8'
    }

    viewBinding {
    
    
        // 启用 ViewBinding
        enabled = true
    }
}

dependencies {
    
    

    implementation 'androidx.core:core-ktx:1.7.0'
    implementation 'androidx.appcompat:appcompat:1.4.1'
    implementation 'com.google.android.material:material:1.5.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

    // 导入 Room 依赖库
    implementation 'androidx.room:room-runtime:2.2.5'
    // 导入注解处理器 ( Kotlin )
    kapt 'androidx.room:room-compiler:2.2.5'
    // 导入注解处理器 ( Java )
    //annotationProcessor 'androidx.room:room-compiler:2.2.5'
}

2. 엔티티 엔티티 클래스 코드


package kim.hsl.roomdemo

import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.PrimaryKey

/**
 * 定义数据库表 Entity 实体 / 同时定义数据库表 和 对鹰的实体类
 * 设置该数据类对应数据库中的一张数据表, 表名为 student
 * 该数据库表中的数据对应一个 Student 类实例对象
 */
@Entity(tableName = "student")
class Student {
    
    
    /**
     * @PrimaryKey 设置主键 autoGenerate 为自增
     * @ColumnInfo name 设置列名称 / typeAffinity 设置列类型
     */
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "id", typeAffinity = ColumnInfo.INTEGER)
    var id: Int = 0

    /**
     * 姓名字段
     * 数据库表中的列名为 name
     * 数据库表中的类型为 TEXT 文本类型
     */
    @ColumnInfo(name = "name", typeAffinity = ColumnInfo.TEXT)
    lateinit var name: String

    /**
     * 年龄字段
     * 数据库表中的列名为 age
     * 数据库表中的类型为 INTEGER 文本类型
     */
    @ColumnInfo(name = "age", typeAffinity = ColumnInfo.INTEGER)
    var age: Int = 0

    /**
     * 有些属性用于做业务逻辑
     * 不需要插入到数据库中
     * 使用 @Ignore 注解修饰该属性字段
     */
    @Ignore
    lateinit var studentInfo: String

    /**
     * 默认的构造方法给 Room 框架使用
     */
    constructor(id: Int, name: String, age: Int) {
    
    
        this.id = id
        this.name = name
        this.age = age
    }

    /**
     * 使用 @Ignore 注解标注构造函数后
     * Room 就不会使用该构造方法了
     * 这个构造方法是给开发者使用的
     */
    @Ignore
    constructor(name: String, age: Int) {
    
    
        this.name = name
        this.age = age
    }

    /**
     * 使用 @Ignore 标签标注后
     * Room 就不会使用该构造方法了
     * 这个构造方法是给开发者使用的
     */
    @Ignore
    constructor(id: Int) {
    
    
        this.id = id
    }

    override fun toString(): String {
    
    
        return "Student(id=$id, name='$name', age=$age)"
    }
}

3. Dao 데이터베이스 액세스 개체 인터페이스 코드


@Dao 주석을 사용하여 인터페이스 클래스를 수정하십시오.

@Insert , @Delete , @Update , @Query 주석을 해당 추가, 삭제, 수정, 쿼리 및 기타 기능을 수정합니다.


전체 코드:

package kim.hsl.roomdemo

import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Update

/**
 * 数据库访问对象接口 / 使用 @Dao 注解修饰
 * 提供数据库的增删改查方法
 */
@Dao
interface StudentDao {
    
    
    /**
     * 向数据库表中插入元素
     */
    @Insert
    fun insert(student: Student)

    /**
     * 从数据库表中删除元素
     */
    @Delete
    fun delete(student: Student)

    /**
     * 修改数据库表元素
     */
    @Update
    fun update(student: Student)

    /**
     * 查询数据库表
     */
    @Query("select * from student")
    fun query(): List<Student>

    /**
     * 根据传入的 id 查询数据库表
     * 在注解中使用 :id 调用参数中的 id: Int
     */
    @Query("select * from student where id = :id")
    fun query(id: Int): List<Student>
}

4. RoomDatabase 데이터베이스 인스턴스 클래스 코드


RoomDatabase 데이터베이스 인스턴스 클래스는 RoomDatabase 추상 클래스를 상속하고 @Database 주석을 사용하여 추상 클래스를 수정해야 합니다.

그 중에서 데이터베이스 접근 객체를 얻기 위한 추상 함수를 정의할 .

이 클래스를 싱글톤 클래스로 정의하고 싱글톤 객체가 초기화될 때 데이터베이스를 생성합니다.


전체 코드:

package kim.hsl.roomdemo

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

@Database(entities = [Student::class], version = 1, exportSchema = false)
abstract class StudentDatabase: RoomDatabase() {
    
    
    /**
     * 获取 数据库访问 对象
     * 这是必须要实现的函数
     */
    abstract fun studentDao(): StudentDao

    companion object {
    
    
        lateinit var instance: StudentDatabase

        fun inst(context: Context): StudentDatabase {
    
    
            if (!::instance.isInitialized) {
    
    
                synchronized(StudentDatabase::class) {
    
    
                    // 创建数据库
                    instance = Room.databaseBuilder(
                        context.applicationContext,
                        StudentDatabase::class.java,
                        "student_database.db")
                        .allowMainThreadQueries() // Room 原则上不允许在主线程操作数据库
                                                  // 如果要在主线程操作数据库需要调用该函数
                        .build()
                }
            }
            return instance;
        }
    }
}

5. 활동 구성 요소에서 Room 프레임워크를 호출하여 데이터베이스에 액세스합니다.


먼저, 데이터베이스 인스턴스 클래스 StudentDatabase를 가져옵니다 .

그런 다음 데이터베이스 액세스 개체 인터페이스 StudentDao를 가져옵니다 .

마지막으로 데이터베이스 액세스 객체 인터페이스 StudentDao의 일련의 메서드를 호출하여 데이터베이스에 액세스합니다.


전체 코드:

package kim.hsl.roomdemo

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import kim.hsl.roomdemo.databinding.ActivityMainBinding
import kotlin.concurrent.thread

class MainActivity : AppCompatActivity() {
    
    
    lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(getLayoutInflater())
        setContentView(binding.root)

        // 获取 StudentDatabase
        var studentDatabase: StudentDatabase = StudentDatabase.inst(this)

        // 获取数据库访问对象
        var studentDao: StudentDao = studentDatabase.studentDao()

        thread(start = true) {
    
    
            // 插入数据
            var s1 = Student("Tom", 18)
            var s2 = Student("Jerry", 16)
            studentDao.insert(s1)
            studentDao.insert(s2)

            // 查询数据
            var students = studentDao.query()
            Log.i("MainActivity", "数据库查询结果 ( 插入后首次查询 ) : " + students)

            // 更新数据 , 将学生年龄都设置为 20
            for (i in 0.. students.size - 1) {
    
    
                students[i].age = 20
                studentDao.update(students[i])
            }
            students = studentDao.query()
            Log.i("MainActivity", "数据库查询结果 ( 修改后查询结果 ) : " + students)

            // 删除数据
            var s_delete = Student(1)   // 删除的元素只需要传入 id 即可
            studentDao.delete(s_delete)
            students = studentDao.query()
            Log.i("MainActivity", "数据库查询结果 ( 删除后查询结果 ) : " + students)
        }


    }
}

추천

출처blog.csdn.net/han1202012/article/details/130568567