本文参考:https://www.jianshu.com/p/3e358eb9ac43
Android 2017 IO大会推出了官方数据库框架:Room。Room对原生的SQLite API进行了一层封装。
Room是一个对象关系映射(ORM)库。Room抽象了SQLite的使用,可以在充分利用SQLite的同时流畅的访问数据库。
Room官方文档:https://developer.android.com/training/data-storage/room/
Room由三个重要的组件组成:Database、Entity、DAO。
Database:包含数据库持有者,并作为与应用持久关联数据的底层连接的主要访问点。
Database对应的类必须满足下面几个条件:
- 必须是abstract类而且的extends RoomDatabase。
- 必须在类头的注释中包含与数据库关联的实体列表(Entity对应的类)。
- 包含一个具有0个参数的抽象方法,并返回用@Dao注解的类。
在运行时,可以通过Room.databaseBuilder() 或者Room.inMemoryDatabaseBuilder()获取Database实例。
Entity:代表数据库中某个表的实体类。
DAO:包含用于访问数据库的方法。
1 添加依赖
implementation "android.arch.persistence.room:runtime:1.1.1"
annotationProcessor 'android.arch.persistence.room:compiler:1.1.1'
testImplementation "android.arch.persistence.room:testing:1.1.1"
2 Entity(实体)
Entity代表存放在数据库某个表中的实体类,默认情况下Room库会把Entity里面所有的字段对应到表中的每一列。Entity就是我们要向数据库中存放的数据类型。
2.1 设置Entity类
@Entity
public class User {
}
Entity的实体类需要添加@Entity注解。
@Entity注解包含的属性 | 含义 |
---|---|
tableName | 设置表名字 |
indices | 设置索引 |
inheritSuperIndices | 父类的索引是否会自动被当前类继承 |
primaryKeys | 设置主键 |
foreignKeys | 设置外键 |
2.2 设置表名
在默认情况下,Entity类名就是表名,但可以通过@Entity的tableName属性设置自定义表名。
@Entity(tableName = "users")
public class User {
...
}
2.3 设置列名
在默认情况下,Entity类中字段名就是表中列的名称,但可以通过@ColumnInfo注解来自定义表中列的名字。比如下列代码,在 user 表中,name 字段对应的列名是 user_name ,age 字段对应的列名是 user_age。
@Entity(tableName = "user")
public class User {
@ColumnInfo(name = "user_name")
private String name;
@ColumnInfo(name = "user_age")
private String age;
}
2.4 设置主键
每个Entity类都需要至少一个主键,即使这个Entity类只有一个属性。
设置主键的方法主要有两种:
1.通过@Entity注解的primaryKeys属性来设置主键,可以设置成单个主键,也可以是复合主键。
@Entity(primaryKeys = {
"name", "age"})
public class User {
private String name;
private String age;
}
2.通过@PrimaryKey注解设置主键
@Entity
public class User {
@PrimaryKey
private String name;
@PrimaryKey
private String age;
}
如果希望主键是自增的,可以设置@PrimaryKey注解中的autoGenerate属性。
@Entity
public class User {
@PrimaryKey(autoGenerate = true)
private String name;
private String age;
}
2.5 设置索引
数据库索引可以提高数据库的访问速度。索引可以分为单列索引和组合索引,可以通过@Entity注解中的indices属性进行设置。
@Entity(indices = {
@Index(value = {
"id"}), @Index(value = {
"name", "age"})})
public class User {
@PrimaryKey
private int id;
private String name;
private String age;
}
索引又可以分为唯一索引和非唯一索引,可以通过@Index注解中的unique设置是否唯一索引。
@Entity(indices = {
@Index(value = {
"id"}, unique = true)})
public class User {
@PrimaryKey
private int id;
private String name;
private String age;
}
2.6 设置外键
因为SQLite是关系形数据库,表和表之间是有关系的。这也就是我们数据库中常说的外键约束(FOREIGN KEY约束)。Room里面可以通过@Entity的foreignKeys属性来设置外键。我们用一个具体的例子来说明。
正常情况下,数据库里面的外键约束。子表外键于父表。当父表中某条记录子表有依赖的时候父表这条记录是不能删除的,删除会报错。一般大型的项目很少会采用外键的形式。一般都会通过程序依赖业务逻辑来保证的。
父表
@Entity(indices = {
@Index(value = {
"id"}, unique = true)})
public class User {
@PrimaryKey
private int id;
private String name;
private String age;
}
子表
@Entity(foreignKeys = @ForeignKey(entity = User.class, parentColumns = "id", childColumns = "userId"))
public class Book {
@PrimaryKey
private int bookId;
private String title;
private int userId;
}
子表Book的foreignKeys设置后,userId属性来源于父表User的id属性。
@Foreignkey属性 | 含义 |
---|---|
entity | parent实体类(引用外键的表的实体) |
parentColumns | parent外键列(要引用的外键列) |
childColumns | child外键列(要关联的列) |
onDelete | 默认NO_ACTION,当parent里面有删除操作的时候,child表可以做的Action动作有: 1. NO_ACTION:当parent中的key有变化的时候child不做任何动作。 2. RESTRICT:当parent中的key有依赖的时候禁止对parent做动作,做动作就会报错。 3. SET_NULL:当paren中的key有变化的时候child中依赖的key会设置为NULL。 4. SET_DEFAULT:当parent中的key有变化的时候child中依赖的key会设置为默认值。 5. CASCADE:当parent中的key有变化的时候child中依赖的key会跟着变化。 |
onUpdate | 默认 |