Android 数据库 Room从入门到进阶

Posted 小陈乱敲代码

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 数据库 Room从入门到进阶相关的知识,希望对你有一定的参考价值。

数据库 Room

Room 在 SQLite 上提供了一个抽象层,以便在充分利用 SQLite 的强大功能的同时,能够流畅地访问数据库。

1.Room 入门

1.gradle添加依赖

build.gradle(Module中的gradle)
Groovy

dependencies 
   
    def room_version = "2.2.5"
    implementation "androidx.room:room-runtime:$room_version"
    annotationProcessor "androidx.room:room-compiler:$room_version" // For Kotlin use kapt instead of annotationProcessor  这里 把  annotationProcessor 替换为 kapt
    // optional - Kotlin Extensions and Coroutines support for Room
    implementation "androidx.room:room-ktx:$room_version"
    // optional - RxJava support for Room
    implementation "androidx.room:room-rxjava2:$room_version"
    // optional - Guava support for Room, including Optional and ListenableFuture
    implementation "androidx.room:room-guava:$room_version"
    // Test helpers
    testImplementation "androidx.room:room-testing:$room_version"

如果使用kotlin :在 gradle的顶部 添加apply plugin: ‘kotlin-kapt’
build.gradle(Module中的gradle)

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'

2.Room重要组件介绍

数据库:包含数据库持有者,并作为应用已保留的持久关系型数据的底层连接的主要接入点,使用 @Database 注释的类是:
扩展RoomDatabase的抽象类
在注释中添加与数据库关联的实体列表
包含具有0个参数且返回使用@Dao注释的类的抽象方法 运行时,通过 Room.databasebaseBuilder()或Room.inMemoryDatabaseBuilder()获取Database的实例
Entity:标识数据库中的表

3.Room 数据库入门级使用

创建实体类(数据表 table)

@Entity()
data class User( 
    // 主键 唯一 autoGenerate = true 表示自增
    @PrimaryKey(autoGenerate = true) val uid: Int?,
    // 表头名
    @ColumnInfo(name = "first_name")
    val firstName: String?,
    // 表头名
    @ColumnInfo(name = "last_name")
    val lastName: String?,
    @ColumnInfo(name = "age")
    val age: Int? = 0,
    @ColumnInfo(name = "city")
    val city: String?
)

创建Dao(操作接口)

@Dao
interface UserDao 
    @Query("SELECT * FROM user")
    fun getAll(): List<User>
    @Query("SELECT * FROM user WHERE uid IN (:userIds)")
    fun loadAllByIds(userIds: IntArray): List<User>
    @Query("SELECT * FROM user WHERE age LIKE :age")
    fun findByAge(age: Int): User
    @Insert
    fun insertAll(vararg users: User)
    @Delete
    fun delete(user: User)

创建 AppDatabase(名字自取)

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

初始化

val db = Room.databaseBuilder(
            applicationContext,
            AppDatabase::class.java, "database-name.db"
        ).build()

AndroidStudio Build -> Rebuild Project 成功之后,就会看到 app/build/generated/source/kapt/debug/包名/ 目录下 AppDatabase_Impl和 UserDao_Impl文件。
至此 数据库创建就完成了。
简单调用 Dao的方法

因为不能在 主线程使用,这里使用协程,也可以使用子线程
 GlobalScope.launch 
            db.userDao().insertAll(User(null, "jack", "love", 10, "AA"))
            val all = db.userDao().getAll()
            Log.d("db_db", "all$all")
        

2.room 常用基础方法举例

对上述进行简单封装
object RoomUtil 
    private val db = Room.databaseBuilder(
        MyAppLication.context,
        AppDatabase::class.java, "database-name.db"
    ).build()
    private val userDao = db.userDao()
    fun getUserDao(): UserDao 
        return userDao
    

@Dao
interface UserDao 
    /**
     * 增
     */
    @Insert()
    fun insert(user: User) // 增加/插入 对象(一行)
    @Insert
    fun insert(users:List<User>) // 增加/插入 对象集合(多行)
    @Insert
    fun insert(vararg user: User) // 增加/插入 n个对象(一行或者多行)
    /**
     * 删
     */
    @Delete
    fun delete(user: User) // 删除 对象(一行)
    @Delete
    fun delete(users: List<User>) // 删除多个对象 (多行)
    @Delete
    fun delete(vararg user: User) // 删除 n个对象(一行或者多行)
    /**
     * 改
     */
    @Update
    fun update(user: User)
    /**
     * 查
     */
    @Query("SELECT * FROM User")
    fun getAll():List<User>

记住,每次修改后,都需要rebuild一下
调用:
        GlobalScope.launch(Dispatchers.IO) 
            val all = RoomUtil.getUserDao().getAll()
        

3.room 数据库 sql语法在room中的使用

在room中的使用(主要以查询为例)如下

@Dao
interface UserDao 
    /**
     * 查
     */
    @Query("SELECT * FROM User")
    fun getAll(): List<User>
    /**
     * 查询 first_name这一列的数据
     */
    @Query("SELECT first_name FROM User")
    fun queryFirstName(): List<String>
    /**
     * 查询 多列 first_name 和 last_name
     */
    @Query("SELECT first_name,last_name From User")
    fun queryManyColumn(): List<User>
    /**
     * 增加查询条件 比如 age的条件 传入参数 在 sql语句中,以 :age 的方式来使用
     */
    @Query("SELECT * FROM user WHERE age=:age")
    fun queryUserByAge(age: Int): List<User>
    @Query("SELECT * FROM User WHERE age BETWEEN :minAge AND :maxAge")
    fun queryUserByAge(minAge: Int, maxAge: Int): List<User>
    @Query("SELECT * FROM User WHERE age IN (:ages)")
    fun queryUserByAge(ages: List<Int>): List<User>

在room中其他方法都可以用Query替代,所以,只要sql语句熟悉,可以就使用@Query(“sql语句”)

@Dao
interface UserDao 
    @Query("INSERT INTO User VALUES (:uid,:firstName,:lastName,:age,:city)")
    fun insertByQ(uid: Int?,firstName:String,lastName:String,age: Int,city:String)
    

4.room 数据库 升级

数据库升级归纳为两类

1.数据库增加表

第一步:创建实体类(数据表)和CarDao

@Entity()
data class Car(
    
    @PrimaryKey(autoGenerate = true)
    var id: Int?,
    @ColumnInfo(name = "car_name")
    var carName: String?,
    @ColumnInfo(name = "value")
    var value: Float? = 0f,
    @ColumnInfo(name = "origin")
    var origin: String?
)
@Dao
interface CarDao 
    @Insert
    fun insert(car: Car)
    @Query("SELECT * FROM Car")
    fun getCars():List<Car>

第二步:通过 Migration 类进行增量升级

注意: 下面的sql语句中的字段,名字 类型 一定要和 Entity Car中的属性完全对应,否则会报错 修改时,根据报错,将属性和字段修改为一致即可
    val MIGRATION_1_2 = object : Migration(1, 2) 
        override fun migrate(database: SupportSQLiteDatabase) 
            database.execSQL("CREATE TABLE `Car` (`car_name` TEXT, 'value' REAL, 'origin' TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT)")
        
    

第三步

private val db = Room.databaseBuilder(
        MyAppLication.context,
        AppDatabase::class.java, "database-name.db")
        .addMigrations(MIGRATION_1_2)
        .build()

第四步:修改AppDatabase

增加 Car class,修改版本号,增加 CarDao关联
@Database(entities = [User::class,Car::class], version = 2)
abstract class AppDatabase : RoomDatabase() 
    abstract fun userDao(): UserDao
    abstract fun carDao(): CarDao

RoomUtil完整代码

object RoomUtil 
    val MIGRATION_1_2 = object : Migration(1, 2) 
        override fun migrate(database: SupportSQLiteDatabase) 
            database.execSQL("CREATE TABLE `Car` (`car_name` TEXT, 'value' REAL, 'origin' TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT)")
        
    
    private val db = Room.databaseBuilder(
        MyAppLication.context,
        AppDatabase::class.java, "database-name.db")
        .addMigrations(MIGRATION_1_2)
        .build()
    private val userDao = db.userDao()
    private val carDao = db.carDao()
    fun getUserDao(): UserDao 
        return userDao
    
    fun getCarDao(): CarDao 
        return carDao
    

2.数据表增加列

第一步:修改实体类(数据表)和UserDao

@Entity()
data class User(
    // 主键 唯一
    @PrimaryKey(autoGenerate = true) val uid: Int?,
    // 表头名
    @ColumnInfo(name = "first_name")
    var firstName: String?,
    // 表头名
    @ColumnInfo(name = "last_name")
    var lastName: String?,
    @ColumnInfo(name = "age")
    var age: Int? = 0,
    @ColumnInfo(name = "city")
    var city: String?,
    // 新增字段(新增列)
    @ColumnInfo(name = "cn_name")
    var cnName:String?
)
// 受影响的方法,进行相应修改,如果没有,则不需要
  @Query("INSERT INTO User VALUES (:uid,:firstName,:lastName,:age,:city,null)")
    fun insertByQ(uid: Int?,firstName:String,lastName:String,age: Int,city:String)

第二步:修改AppDatabase

增加版本号
@Database(entities = [User::class,Car::class], version = 3)
abstract class AppDatabase : RoomDatabase() 
    abstract fun userDao(): UserDao
    abstract fun carDao(): CarDao

第三步:增加Migration

val MIGATION_2_3 = object :Migration(2,3)
        override fun migrate(database: SupportSQLiteDatabase) 
            database.execSQL("ALTER TABLE User ADD COLUMN cn_name TEXT")
        
    
    
        private val db = Room.databaseBuilder(
        MyAppLication.context,
        AppDatabase::class.java, "database-name.db")
        .addMigrations(MIGRATION_1_2)
        .addMigrations(MIGATION_2_3)
        .build()

RoomUtil完整代码

object RoomUtil 
    val MIGRATION_1_2 = object : Migration(1, 2) 
        override fun migrate(database: SupportSQLiteDatabase) 
            database.execSQL("CREATE TABLE `Car` (`car_name` TEXT, 'value' REAL, 'origin' TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT)")
        
    
    val MIGATION_2_3 = object :Migration(2,3)
        override fun migrate(database: SupportSQLiteDatabase) 
            database.execSQL("ALTER TABLE User ADD COLUMN cn_name TEXT")
        
    
    private val db = Room.databaseBuilder(
        MyAppLication.context,
        AppDatabase::class.java, "database-name.db")
        .addMigrations(MIGRATION_1_2)
        .addMigrations(MIGATION_2_3)
        .build()
    private val userDao = db.userDao()
    private val carDao = db.carDao()
    fun getUserDao(): UserDao 
        return userDao
    
    fun getCarDao(): CarDao 
        return carDao
    

来自:https://www.yuque.com/linxiaomo-wcgu0/wwowft/gukbhy

最后

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。

相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

全套视频资料:
一、面试合集

二、源码解析合集

三、开源框架合集


欢迎大家一键三连支持,若需要文中资料,直接点击文末CSDN官方认证微信卡片免费领取

以上是关于Android 数据库 Room从入门到进阶的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin基础从入门到进阶系列讲解(入门篇)Android之GSON的使用

Kotlin基础从入门到进阶系列讲解(进阶篇)Android之Activity的生命周期

Android从入门到进阶之高级控件

Android从入门到进阶之高级控件

Android Room Database:如何嵌入多个实体

2023最新Android进阶笔记,八大模块,从入门到精通