Android Jetpack架构组件-Room基本使用

一、简介

Room有三个主要的组件:Database、Dao、Entity

  • 数据库(Database):你可以使用该组件创建数据库的持有者。该注解定义了实体列表,该类的内容定义了数据库中的DAO列表。这也是访问底层连接的主要入口点。注解类应该是抽象的并且扩展自RoomDatabase。在运行时,你可以通过调用Room.databaseBuilder()(理解为常规数据库的定义)或者Room.inMemoryDatabaseBuilder()(数据保存在内存中,即程序关掉,数据丢失)获取实例。

  • 实体(Entity):这个组件代表了持有数据库表记录的类。对每种实体来说,创建了一个数据库表来持有所有项。你必须通过Database中的entities数组来引用实体类。实体的每个成员变量都被持久化在数据库中,除非你注解其为@Ignore

  • 数据访问对象(DAO):这个组件代表了作为DAO的类或者接口。DAO是Room的主要组件,负责定义访问数据库的方法。被注解@Database的类必须包含一个无参数的抽象方法并返回被@Dao注解的类型。当编译时生成代码时,Room会创建该类的实现。

Database、Dao、Entities 和 app 的关系图如下所示:

截屏2020-03-3114.55.04.png

二、如何使用

我们以简单示例来具体实现如上核心类:

1.添加依赖

添加相关room依赖包Room版本说明,读者可根据如上链接,获取最新版本及按需依赖即可

2.定义Database类

/**
 * des:Database
 * author:onexzgj
 */
@Database(entities = [Cheese::class], version = 1)   //注释1
abstract class CheeseDb : RoomDatabase() {

    abstract fun cheeseDao(): CheeseDao

    companion object {
        private var instance: CheeseDb? = null

        fun get(context: Context): CheeseDb {
            if (instance == null) {
                //注释2
                instance = Room.databaseBuilder(context, CheeseDb::class.java, "onexzgj")
                //是否允许在主线程进行查询
                    .allowMainThreadQueries()
                    .addCallback(object : RoomDatabase.Callback() {
                        override fun onCreate(db: SupportSQLiteDatabase) {
                            super.onCreate(db)
                        }         
                    })
                    .build()
            }
            return instance!!
        }
}
  • 在注释1处
    使用@Database注解,表示是数据库的入口类,参数entities是数组类型,需要将当前APP中的所有涉及到的数据库表类,都写入这个参数,version参数表示当前数据库的版本,其实还有一个参数为 exportSchema =true,默认为true,按照字面意思为导出数据库概要,即每次操作数据库的一个摘要信息,但是需要注意的事,如果手动设置为true时,需要在build.gradle中的指定导出文件的位置,如下所示:
  defaultConfig {
        ...
        javaCompileOptions{
            annotationProcessorOptions{
                arguments=["room.schemaLocation":"$projectDir/schemas".toString()]
            }
        }
    }

这个时候,等程序运行之后,就会在根目录生成schemas目录,并且产生一个json文件,如下所示:


image.png
  • 在注释2处
    可以根据项目需要选择内存数据库,且还有如下回调方法,如下所示:
        //创建一个内存数据库
        //但是这种数据库的数据只存在于内存中,也就是进程被杀之后,数据随之丢失
        Room.inMemoryDatabaseBuilder(...)
                //是否允许在主线程进行查询
                    .allowMainThreadQueries() 
                //数据库创建和打开后的回调
                .addCallback()
                //设置查询的线程池,一般不需要设置
                .setQueryExecutor()
                .openHelperFactory()
                //room的日志模式
                .setJournalMode()
                //数据库升级异常之后的回滚,默认重新进行创建
                .fallbackToDestructiveMigration()
                //数据库升级异常后根据指定版本进行回滚
                .fallbackToDestructiveMigrationFrom()
                // 数据库迁移升级时使用,后文会提到
                 .addMigrations(CacheDatabase.sMigration)

3.定义Dao

@Dao
interface CheeseDao {

    @Query("select * from cheese order by name ")
    fun findAllCheese(): DataSource.Factory<Int, Cheese>    //注释1

    @Query("select * from cheese order by name ")
    fun getAllCheese(): List<Cheese>?      //注释2

    @Insert
    fun insert(cheeses: List<Cheese>)

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insert(cheese: Cheese)

    @Delete
    fun delete(cheese: Cheese)
}
  • 注释1处
    返回的数据类型为DataSource.Factory<Int,Cheese>,注释2处返回的数据类型为List<Cheese> 从这里可以看到Room数据库是原生支持Paging框架,如果不了解Paging的可以查看笔者之前的文章Paging框架

  • 注释2处
    返回的数据类型为 List<Cheese>? ,则可以直接返回List集合
    当然这里也可以搭配Rxjava2使用,返回对象为 Flowable<List<CheeseAndUser>> ,后续再介绍

4、定义Entity

@Entity
data class Cheese(
    @PrimaryKey(autoGenerate = true) val id: Int, val name: String
)

通过@Entity注解标注的类,则表示这个类会映射到数据库中,默认表名为类名,
通过@ PrimaryKey,标明主键,通过设置autoGenerate参数设置true,则表示主键会自增长

5、代码中使用

        val allCheese = CheeseDb.get(this).cheeseDao().getAllCheese()
        Log.d("DATATA", allCheese?.get(0)?.name + ":" + allCheese?.size)

运行结果如下所示:


运行结果.png

到这里相信对Room数据库有一个基本的了解,如果了解Orm或者GreenDao的同学,应该对上面的步骤或者创建不难理解,接下来介绍核心类的具体参数的含义及用法

三、核心类属性讲解

3.1 、@Entity注解包含的属性有:

tableName:设置表名字,默认是类的名字。
indices:设置索引,按需添加,会提高查询速度,增加更新和新增的操作时间
inheritSuperIndices:父类的索引是否会自动被当前类继承,没用到过,暂不解释
primaryKeys:设置主键,一般通过直接在主键字段上添加@PrimaryKey
foreignKeys:设置外键。
Ignore:设置不需要映射到数据库中的字段可以使用,则不会在表中出现该字段

如下所示:

@Entity(tableName = "table_cheese")
data class Cheese(
    @PrimaryKey(autoGenerate = true) val id: Int, 
    
    @ColumnInfo(name = "testName")
    val name: String,
    @Ignore
    val temp:String
)

3.2、@Query注解是

它是DAO类中使用的主要注释,允许对数据库执行读/写操作。@Query在编译的时候会验证准确性,所以如果查询出现问题在编译的时候就会报错,如字段拼写常规错误等。

Room还会验证查询的返回值,如果返回对象中的字段名称与查询响应中的相应列名称不匹配的时候,Room会通过以下两种方式之一提醒您:
如果只有一些字段名称匹配,它会发出警告。
如果没有字段名称匹配,它会发生错误。

@Query注解value参数:查询语句,根据需求,完成查询sql语句即可。

 @Query("select * from cheese  where name ==:name ")
 fun getCheese(name:String): List<Cheese>?

四、结语

到这里,Room的基本使用就差不多介绍完成了,那么在实际开发中,仅仅掌握基本使用,是远远不够的,如多表查询,一对一、一对多等关系的查询如何实现?配合Rxjava/LiveData/Paging的使用

本文示例代码已上传至Jetpack_Component

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容