首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Room数据库总结

目录

RoomEntityDao数据映射事务Database数据库升级测试开始测试查询模式LiveDataRxJava需要注意的地方代码参考

这不是一篇很好的入门文章,仅做记录使用,更好的还是直接参考文末的官方向导

Room

Room 是Android提供的操作数据库的高Api架构,避免了直接使用SQLite的一些重复代码和麻烦,而且属于Android Architecture Components,如果你还在用着SQLite可以尝试使用Room.使用annotationProcessor来自动生成代码.

代码侵入很小,很容易从SQLite过度到Room.

提供数据库升级测试,提供sql编译时校验;

灵活的返回对象,支持LiveData,RxJava.

Room 主要由三个部分

Database : 数据库持有者,使用@Database来标识,用来连接Entity,DAO,配置数据库的一些功能;

Entity :用来映射表结构的实体;

DAO : 包含操作数据的方法

来源出自Android Develpers

上面是三者的关系,只有在Database中配置了的EntityDao才会被编译进程识别,生成对应的代码

来看看配置完成后项目操作数据库的所有代码,这里我直接拿了官方代码的例子

AppDatabase.java

UserDao.java

User.java

没有对比就没有伤害,这是用Sqlte直接写的,很难维护,Room一行,SQLite无数行,修改的时候要了人的老命

当然上面仅是一些基础功能,大致介绍了Room的结构,下面正式开始Room的学习.

首先添加依赖

Entity

和其它关系映射数据库一样,首先定义表结构,也就是Entity.制定表结构

上面的代码,主要介绍了,关于Entity的主要代码,以及所有的注解Api,上面对于表关系的描述,其实可以不加,但是一个好的表关系,能够更好的维护表的数据;

补充一下onUpdate 和 onDelete 的参数

NO_ACTION 什么也不做

RESTRICT 约束模式,就拿上面的例子简单来说,Book的主键 id 是 Page 的 book_id外键,那么他们俩是通过 id 和book_id进行约束的,在Page的book_id外键存在的时候不允许删除Book的id和修改Book的id,因为一旦修改成功,那么Page就乱掉了,无法形成对应关系,就成了脏数据

SET_DEFAULT,SET_NULL 两个做的事情是一样的,一个设置null一个设置默认值,举个列子,你现在删除了Book id=2的数据,那么Page 的 book_id=2 的这条数据的book_id 是给他设置 null 或者默认值,因为之前的id没了

CASCADE 关联默认,这个意识是,你删了Book id=2 的数据,对应的Page book_id的数据也会被删除,更新了id那么对应的Page book_id字段也会更新

那么到这里Entity的所有内容已经说完了.

Dao

这里的Dao是定义数据处理的地方,就像Retrofit的retrofit.create(GitHubService.class);里的Services,用户定义要查询的语句,返回的内容,然后返回用户想要的数据,Room帮用户在编译时生成对应的代码.

上面的例子显示了基本的增删改查,可以发现Room会根据返回值自动推测结果,例如删除的时候你可以定义void,那么久没有返回值,当你改为int时,则会返回对应的行数.而且在写Sql语句的时候as会提示你使用哪个字段,例如book,当我打出b的时候回提示book,防止拼错等低级操作,如果想动态填充数据使用:xxx

然后解释一下 Insert,Update的用法.

有时插入数据和更新数据会产生冲突,所以就有了冲突之后要怎么解决,SQLite对于事务冲突定义了5个方案

OnConflictStrategy

REPLACE,见名知意,替换,违反的记录被删除,以新记录代替之

ignore 违反的记录保持原貌,其它记录继续执行

fail 终止命令,违反之前执行的操作得到保存

abort 终止命令,恢复违反之前执行的修改

rollback 终止命令和事务,回滚整个事务

事务解决由上到下越来越严谨

好了上面是基本操作,下面搞点高大上的,因为关系型数据库避免不了的还有一对一,一对多,多对多的关系

一本书有很多页,典型一对多.

表结构

Book.java

Book 的id 和 Page 的 book_id 约束

PageDetail.java

数据映射

不仅实体可以映射出表结构,查出的数据也可以通过映射到实体

这里在 public List

getPageInfo(int bookId);中定义了一个返回的实体PageDetail,如果表中查询出的字段和实体不匹配可以使用ColumnInfo来指定对应的关系!

事务

引入事务的概念Transaction,有的查询语句里面会有一个以上的操作,例如查完book再查page,那么被事务注解的方法,两者属于同一个事务,只有事务中的两个原子操作成功了,这次事务才是成功!

注意下面的BookInfo

BookInfo.java

上面有说过,Room会根据查询的字段和返回值的字段进行比对,然后生成对应的实体,

@Embedded: 嵌入,在select * from book where id = :bookId这句话查询出的内容应该是 book表中的字段,但是用了Book对象来接,这里Room把字段装箱成了Book

@Relation 虽然查询的是 book,而且sql没有写关联两个标的操作,但是确把对应的关系查出来了,这里Relation就起到了这个作用,仔细看方法的注释.

如果上面的方法能够理解,那我们继续!

Database

Database起了一个连接作用,entities规定了哪些实体参与映射,version标识数据库版本,exportSchema是否导出数据库结构数据,他是个抽象类, public abstract BookDao getBookDao();把我们刚刚写好的Dao定义到里面,APT才会生成对应的查询方法

AppDatabase.java

仔细看完上面的代码.只要能得出Database是对EntityDao管理的就好.

@TypeConverters这个方法写在Database那就是全局应用,写在Entity就只应用在本表中.也是根据返回值和参数来规定什么时候使用.

Trade.java

数据库升级

刚才在Database看到了这么一行代码:

new Migration(1, 2)意思是版本1~2到的升级,当数据库版本1到2的时候就会回调这个方法,上面的代码就是添加User表.

其实我们在以往其它SQLite架构里面,升级数据的时候不需要主动添加表,顶多改下版本号就完了,例如GreenDao.但是Room不行,他会在表中增加哈希码.增加表必须要有更新的操作!

如果你想跨版本new Migration(1, 3),那就是旧版本1,新代码的版本是3那么就回调里面的方法,而2~3不会调用这个方法!

测试

Room支持数据库升级测试,在以往的开发过程中,由于增加了字段而没有执行对应的sql,导致调用数据库的崩溃,Room提供了版本更新时的测试,原理是根据每个版本的表结构生成对应的文件,当测试的时候会把以往的版本信息读取出来,然后结合要升级的版本结构去验证是否成功!有了这个数据,无论从什么版本升级都有据可查!

配置gradle

编译一下就会在app->schemas->包名下生成对应的表关系文件

开始测试

因为要操作数据库,所以要在androidTest中使用

InstrumentationRegistry用来模拟环境可以从中获取上下文对象等.

MigrationTestHelper(Instrumentation instrumentation ,String assetsFolder ,SupportSQLiteOpenHelper.Factory openFactory ),这里注意第二个参数assetsFolder,就是那些自动生成的app->schemas文件夹,传Database路径就好

migrationTestHelper.createDatabase(AppDatabase.DATABSE_NAME, 1);

第一个参数数据库名称,

第二个参数版本号,这个方法是为了创建对应的版本数据的

migrationTestHelper.runMigrationsAndValidate(AppDatabase.DATABSE_NAME, 3, false, MIGRATION1_2, MIGRATION2_3);

参数一: 数据库名,

参数二: 要升级到哪个版本的数据库,

参数三: 出问题是否删除表,true,删除表;

参数四: 升级的回调实现

查询模式

Room数据库不允许在UI线程执行任何数据库相关的操作,虽然可以通过设置 .allowMainThreadQueries()必过校验但是不建议,;那么怎么解决插入在异步线程,查询也在异步线程的同步问题呢?Room数据库提供了LiveData

LiveData

这里我们需要添加

然后就可以使用AndroidViewModel

MainActivity.java

当查询的内容发生变化的时候自动会回调onChanged方法

详情可以看代码[源码地址]()

RxJava

添加依赖

和其它没什么区别,就是包裹一下返回值

获取数据

需要注意的地方

代码

因为先写的代码再写的文章,就显得逻辑没那么通畅,没有按照先简单后容易的方式去写,而是直接把遇到的一下说完,希望有的地方能帮助到你,已经同步代码放到了GitHub上;又因为代码有注释,所以没有将Api抽离出来单独介绍.

RoomOrmDemo

参考

Room Persistence Library Part of Android Jetpack.

此处应有签名

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181026G0ODST00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券