➤ Jetpack 笔记 Room 的使用

前两天我学习的是LifeCycle ViewModel LiveData 以及DataBinding 今天我要学习的是Room

在这里插入图片描述

Room的介绍

Android官方ORM库Room
Android采用SQLite作为数据库存储,开源社区常见的ORM(Object Relational Mapping)库有ORMLite GreenDAO 等,Room与其他库一样都是在SQLite上提供一层封装。

Room重要的概念
Entity 实体类,对应的是数据库中的一张表结构,使用注解@Entity标记
Dao 包含访问一系列访问数据库的方法,使用注解@Dao标记
Database 数据库持有者,作为与应用持久化相关数据的底层连接的接入点。使用注解
@Database标记 ,另外需要满足以下条件 定义类必须是一个继承于RoomDatabase的抽象类,在注解中需要定义与数据库相关联的实体类列表。包含一个没有参数的抽象方法并且返回一个Dao对象。

在这里插入图片描述

Room的使用

这里我用Kotlin 代码做案例,最后附加上java 代码。

引入依赖库

apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: "kotlin-kapt"
    implementation "androidx.room:room-runtime:2.2.6"
    kapt "androidx.room:room-compiler:2.2.6"
    implementation "androidx.room:room-ktx:2.2.6"

Room 三大部分概述

Room组要由三大部件组成:@Entity,@Dao和@Database。
简单来讲,@Entity是用来创建具体数据表的,其以数据model类的形式,展现一个数据表中的各个属性。
@Dao是个接口类,一般提供某张表的各种增删改查的方法
@Database作为数据库的根基,数据库文件的位置,数据库的创建都是在此类中完成。@Database注解的类一般会提供一个单例对象,即数据库操作对象,然后会有各个数据表的注册(或声明),以及这些数据表对象的获取的抽象方法放到这个类中。@Database注解的类是一个抽象类。

创建Entity

Kotlin中创建Entity跟Java 差不多,也就是创建一个数据模型给Room去使用,有两种写法 一种是Data 写法 ,还有一种Class 格式,因我我也是最近刚学完的Kotlin 很多地方不是很熟练,比较倾向于 Class格式的写法

@Entity(tableName = "student")
class Student() {
    @PrimaryKey(autoGenerate = true)
    var id: Int = 0
    var name: String = ""
    var age: Int = 0

    constructor(name: String, age: Int) : this() {
        this.name = name
        this.age = age
    }

    constructor(id: Int) : this() {
        this.id = id
    }

    constructor(id: Int, name: String, age: Int) : this() {
        this.id = id
        this.name = name
        this.age = age
    }
}

创建Dao

@Dao
interface StudentDao {
    
    @Insert
    fun insertStudent(vararg student: Student)

    @Delete
    fun deleteStudent(vararg students: Student)

    @Update
    fun updateStudent(vararg students: Student)

    @Query("SELECT * FROM student")
    fun getAllStudent(): List<Student>

    @Query("DELETE FROM student")
    fun deleteAllStudents()
    
  // 使用了LiveData 数据变动直接通知页面
    @Query("SELECT * FROM student")
    fun getAllStudentsLive(): LiveData<List<Student>>

}

创建Database

这是我自己的写法,因为Kotlin 不是很熟练,可能有些地方用的不是很恰当,以后随着我Kotlin的技能不断提升,我会替换的。

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

    companion object {
        private val DATABASE_NAME = "my_db.db"
        @Volatile
        private var mInstance: MyDatabase? = null

        @Synchronized
        fun getInstance(context: Context): MyDatabase {
            mInstance?.let {
                return it
            }?:let {
                mInstance = Room.databaseBuilder(
                    context.applicationContext,
                    MyDatabase::class.java,
                    DATABASE_NAME
                ).fallbackToDestructiveMigration()
                    .build()
                return mInstance as MyDatabase
            }
        }
    }
    
    abstract fun getStudentDao(): StudentDa
}

Repository类(与Room 无关)
这里我为了方便操作,写了一个Repository类,放在子线程对数据库进行操作,不知道写的是否合理,也希望能遇到大佬帮忙看一下。

class StudentRepository(context: Context) {

    /**
     *  数据处理类, 对数据库的操作属于耗时操作 我这边放在了子线程中处理
     *   使用LiveData 随时变更数据
     **/

    var studentDao: StudentDao

    init {
        val instance = MyDatabase.getInstance(context)
        studentDao = instance.getStudentDao()
    }

    suspend fun insertStudent(students: Student) = withContext(Dispatchers.IO) {
        studentDao.insertStudent(students)
    }

    suspend fun deleteStudent(students: Student) = withContext(Dispatchers.IO) {
        studentDao.deleteStudent(students)
    }


    suspend fun deleteAllStudents() = withContext(Dispatchers.IO) {
        studentDao.deleteAllStudents()
    }

    suspend fun updateStudent(students: Student) = withContext(Dispatchers.IO) {
        studentDao.updateStudent(students)
    }

    fun getAllStudentsLive(): LiveData<List<Student>> {
        return studentDao.getAllStudentsLive()
    }

}

viewModel类 (与Room 无关)

class StudentViewModel(application: Application) : AndroidViewModel(application) {
    var repository: StudentRepository = StudentRepository(application)

    //启用协程处理
     fun insertStudent(students: Student) {
        viewModelScope.launch {
            repository.insertStudent(students)
        }
    }

    fun updateStudent(students: Student) {
        viewModelScope.launch {
            repository.updateStudent(students)
        }
    }

     fun deleteStudent(students: Student) {
        viewModelScope.launch {
            repository.deleteStudent(students)
        }

    }

     fun deleteAllStudents() {
         viewModelScope.launch {
             repository.deleteAllStudents()
         }

    }

    fun getAllStudentsLive(): LiveData<List<Student>> {
        return repository.getAllStudentsLive()
    }
}

这些就是数据库进行增删改查的操作

Room的升级

例如新增一个Sex字段

@Entity(tableName = "student")
class Student() {
    @PrimaryKey(autoGenerate = true)
    var id: Int = 0
    var name: String = ""
    var age: Int = 0
    var sex: Int = 0

    constructor(name: String, age: Int,sex:Int) : this() {
        this.name = name
        this.age = age
        this.sex = sex
    }

    constructor(id: Int) : this() {
        this.id = id
    }

    constructor(id: Int, name: String, age: Int) : this() {
        this.id = id
        this.name = name
        this.age = age
    }
}

在Database中需要修改

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

    companion object {
        private val DATABASE_NAME = "my_db.db"

        @Volatile
        private var mInstance: MyDatabase? = null

        @Synchronized
        fun getInstance(context: Context): MyDatabase {
            mInstance?.let {
                return it
            } ?: let {
                mInstance = Room.databaseBuilder(
                    context.applicationContext,
                    MyDatabase::class.java,
                    DATABASE_NAME
                ).addMigrations(migration1to2)
                    .fallbackToDestructiveMigration()
                    .build()
                return mInstance as MyDatabase
            }
        }
        // 增加的版本更新
        private val migration1to2: Migration = object : Migration(1, 2) {
            override fun migrate(database: SupportSQLiteDatabase) {
                database.execSQL("ALTER TABLE student ADD COLUMN 'sex' INTEGER NOT NULL")
            }
        }

    }


    abstract fun getStudentDao(): StudentDao


}

fallbackToDestructiveMigration()
当更新失败
设置破坏式迁移,数据与结构全清空

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值