目录
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中配置了的Entity和Dao才会被编译进程识别,生成对应的代码
来看看配置完成后项目操作数据库的所有代码,这里我直接拿了官方代码的例子
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是对Entity和Dao管理的就好.
@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.
此处应有签名
领取专属 10元无门槛券
私享最新 技术干货