慕课网-jetpack实战课程笔记
room数据库众多注解
Room是Google为了简化旧式的SQLite操作专门提供的。
1.拥有SQLite的所有操作功能;
2.使用简单(类似于Retrofit库),通过注解的方式实现相关功能。编译时自动生成实现类Impl
3.LiveData,LifeCycle,Paging天然融合,支持在module的build.gradle文件里定义工程的缓存目录
android{
defaultConfig{
javaCompileOptions{
//定义工程的缓存目录
annotationProcessorOptions{
arguments = ["room.schemaLocation":"$projectDir/schemas".toString()]
}
}
}
buildTypes{
//...
}
}
在libnetwork下创建CacheDatabase,提供缓存能力。因为Room通过注解来实现相关功能,编译时通过navannotation process来生成相关实现类。所以要把CacheDatabase写成abstract类,运行时生成cacheDatabase的实现类。
初始化写在静态代码块中。
static {
//创建一个内存数据库-->这种数据库的数据只存在于内存中,也就是进程被杀之后,数据随之丢失
//Room.inMemoryDatabaseBuilder()
database = Room.databaseBuilder(AppGlobals.getApplication(), CacheDatabase.class, "ppjoke_cache")
//是否允许在主线程进行查询
.allowMainThreadQueries()
//数据库创建和打开后的回调
//.addCallback()
//设置查询的线程池
//.setQueryExecutor()
//.openHelperFactory()
//room的日志模式
//.setJournalMode()
//数据库升级异常之后的回滚
//.fallbackToDestructiveMigration()
//数据库升级异常后根据指定版本进行回滚
//.fallbackToDestructiveMigrationFrom()
// .addMigrations(CacheDatabase.sMigration)
.build();
}
compileOnly:只参与编译,不参与打包。
Room数据库注解:
1.@Database
2.@Columninfo:数据库表中的字段<–>java bean;如果不添加注解,那么数据库表列的字段名称和java bean中的属性名称要严格一致;如果不一致,需要添加注解来设置别名。默认可以不写
//@ColumnInfo(name = “_datae”),指定该字段在表中的列的名字–;列名是datae
public byte[] data;
3.@Dao
某个类被@Dao注解了的话,它就是真正能操作数据库的一个类。可以标记在抽象类或者接口上。
@Insert
@Query
@Delete
@Update
4.Entity
当一个类被注解为@Entity并且引用到带有@Database 注解的entities属性,Room为这个数据库做的entity创建一个数据表。
tableName:设置表名字。默认是类的名字。
indices:设置索引。
inheritSuperIndices:父类的索引是否会自动被当前类继承。
primaryKeys:设置主键。
foreignKeys:设置外键。
ignoredColumns : 被忽略的字段。
默认情况下,Room为每个定义在entity中的字段创建一个列,如果一个entity的一些字段你不想持久化,可以使用@Ignore注解它们。为了持久化一个字段,Room必须有它的入库
5.@Embedded:有些情况下会需要将多个对象组合成一个对象。对象和对象之间是有嵌套关系的。Room中就可以使用@Embedded注解来表示嵌入。然后,可以像查看其他单个列一样查询嵌入字段。
https://www.jianshu.com/p/72c8efc3ad87
public class Address {
public String street;
public String state;
public String city;
@ColumnInfo(name = "post_code")
public int postCode;
}
@Entity
public class User {
@PrimaryKey
public int id;
public String firstName;
@Embedded
public Address address;
}
@TypeConverte:类型转换。标记一个方法作为类型转换。
@Ignore
@PrimaryKey
@ForeignKey
@Index
@OnConflictStrategy
@RawQuery
@Relation
6.tableName
设置表名,如果未设置,默认为类名
@Entity(tableName = "users")
class User {
...
}
涉及的注解如下:
@indices:设置索引。
@inheritSuperIndices:父类的索引是否会自动被当前类继承。
@primaryKeys:设置主键。
@foreignKeys:设置外键。
@ignoredColumns : 被忽略的字段。
Primary Key(主键)
(1)如果要定义复合主键,则应使用primaryKeys()方法。
(如何表中每一个字段都可能重复,无法使用单一字段作为主键,这时我们可以将多个字段设置为复合主键,由复合主键标识唯一性)
@Entity(primaryKeys = {"firstName", "lastName"})
class User {
}
(2) 每个{@Entity}必须声明一个主键,除非它的一个超类声明了主键。如果{@Entity}及其超类都定义了{@PrimaryKey},则子类的{@PrimaryKey}定义将覆盖父项的{@PrimaryKey}。
7.indices索引
数据库索引用于提高数据库表的数据访问速度。数据库里面的索引有单列索引和组合索引。Room里面可以通过@Entity的indices属性来给表格添加索引。
@Entity(indices = {@Index("firstName"),
@Index(value = {"last_name", "address"})})
public class User {
@PrimaryKey
public int id;
public String firstName;
public String address;
@ColumnInfo(name = "last_name")
public String lastName;
@Ignore
Bitmap picture;
}
8.foreignKeys外键
因为SQLite是关系形数据库,表和表之间是有关系的。这也就是我们数据库中常说的外键约束(FOREIGN KEY约束)。Room里面可以通过@Entity的foreignKeys属性来设置外键。我们用一个具体的例子来说明。
通过foreignKeys之后Book表中的userId来源于User表中的id,如下:
@Entity(indices = {@Index(value = {"first_name", "last_name"},
unique = true)})
public class User {
@PrimaryKey
public int id;
@ColumnInfo(name = "first_name")
public String firstName;
@ColumnInfo(name = "last_name")
public String lastName;
@Ignore
Bitmap picture;
}
@Entity(foreignKeys = @ForeignKey(entity = User.class,
parentColumns = "id",
childColumns = "user_id"))
public class Book {
@PrimaryKey
public int bookId;
public String title;
@ColumnInfo(name = "user_id")
public int userId;
}