前言
上篇我们分析了对于Android架构体系最终要的Viewmodel组件,它可以实现数据和view之间的管理,并且能提供组件间的通讯(注意fragment获取viewmodel时传入的对象要一致)。
那么,接下来我们就学习一下和Livedata完美兼容的数据库——Room
Room是Google推出的Android架构组件库中的数据持久化组件库, 也可以说是在SQLite上实现的一套ORM解决方案。
Room数据存储库支持返回Livedata对象的可观察查询,当数据库更新时,Room 会生成更新 LiveData 对象所需的所有代码。在需要时,生成的代码会在后台线程上异步运行查询。此模式有助于使界面中显示的数据与存储在数据库中的数据保持同步。
Room是什么?
Room主要包含四个步骤:
-
Entity:表示持有数据库行的类(即数据表结构)。对于每个实体,将会创建一个数据库表来持有他们。你必须通过Database类的entities数组来引用实体类。实体类的中的每个字段除了添加有 @Ignore注解外的,都会存放到数据库中。
-
Dao:表示作为数据访问对象(DAO)的类或接口。DAO是Room的主要组件,负责定义访问数据库的方法。由 @Database注解标注的类必须包含一个无参数且返回使用 @Dao注解的类的抽象方法。当在编译生成代码时,Room创建该类的实现。
-
Database :用来创建一个数据库持有者。注解定义一系列实体,类的内容定义一系列DAO。它也是底层连接的主入口点。
-
Room :数据库的创建者 & 负责数据库版本更新的具体实现者
其关系图如下所示:
Room的基本使用
1. 创建Entity实体(Entity)
@Entity
public class User {
// 主键-设置自增长 默认false
@PrimaryKey(autoGenerate = true)
private int uid;
// 数据表中的名字 默认字段名
@ColumnInfo(name = "name")
private String name;
private int age;
//注解该字段不加入数据表中
@Ignore
private String sex;
//引用其它实体类
@Embedded
private Education mEducation;
// ...省略getter and setter
public class Education{
private String HighSchool;
private String University;
}
}
我们先来介绍下实体类中的注解及其含义:
@Entity
:数据表的实体类@PrimaryKey
:每一个实体类都需要一个唯一的标识即主键。@ColumnInfo
:数据表中字段的名字@Ignore
:标注不需要加入数据表中的属性@Embedded
:实体类中引用其它实体类@ForeignKey
:外键约束
1.1 @Entity——实体类
1.1.1 指定表名
用@Entity标注的类,默认表示当前的类名即为表名,当然我们也可以指定表名:
@Entity(tableName = "other")
1.1.2 设置主键或复合主键
我们也可以在@Entity中设置主键、复合主键:
这里注意:
主键的字段不能为null,也不允许有重复值
复合主键的字段不能为null,所以需要加上@Nullable注解
复合主键只有主键都一致,才会覆盖,相当于&&
@Entity(primaryKeys = "uid")
public class User {
...}
@Entity(primaryKeys = {
"uid", "name"})
public class User {
@Nullable //复合主键时需注意,不能为null
private String name;
}
1.1.3 设置索引
数据库添加索引,可以提高数据库访问速度。
索引可以有单列索引,组合索引及索引的唯一性
索引的唯一性unique = true,表示数据不可重复,但在组合索引中不作为条件依据
//单列索引 @Entity(indices = {@Index(value = "name")})
//单列索引唯一性 @Entity(indices = {@Index(value = "name", unique = true)})
//组合索引 @Entity(indices ={@Index(value = {"name","age"})})
//组合索引唯一性 @Entity(indices ={@Index(value = {"name","age"},unique = true)})
//当然可以混起来用 如下:
@Entity(indices ={
@Index(value = "name"),@Index(value = {
"name","age"},unique = true)})
public class User {
...}
1.1.4 外键约束
我们再创建一个实体类Book
@Entity(foreignKeys = @ForeignKey(entity = User.class,parentColumns = "uid",childColumns = "fatherId"))
public class Book{
private int bookId;
private String bookName;
private int fatherId;
}
我们看下这段注解的含义:
它表示Book实体类依附于User实体类entity = User.class
并且注明父类User的列uid字段parentColumns = "uid"
子类Book的列fatherId字段childColumns = "fatherId"
表明了子类的fatherId相当于父类uid(fatherId == uid)
@ForeignKey
还有两个属性onDelete
和onUpdate