Room
三个部分:Entitiy,Dao,Database,
Entity
SQLite表的映射类,每个Entity至少有一个主键(定义主键有两种方式);至少有一个无参构造方法或参数基于类型和名称匹配属性的构造方法。构造参数不必接受所有属性作为参数,如果一个属性没有在构造参数被赋值,它应该被public
修饰或有一个被public
修饰的setter方法。如果有匹配的构造参数,Room将总是使用它,如果你不想使用它,使用@Ignore
标记。如果不想持久化某些属性,也可以使用@Ignore
标记这些属性。
@Entity
用于标记要被持久化的类。
tableName:该类在SQLite中对应的表名,默认为类名。
indices:表中索引的集合(不懂什么作用)。
inheritSuperIndices:默认false,当设置为true时,该类继承树上所有父类的属性也会被保存到这个实体中,即使父类的该值设置为false。当从父类继承一个index后会根据@Index
对其重命名,因为SQLite不允许在多个表中使用相同index名。
primaryKeys:声明任意数量主键,默认为空。
ForeignKey:声明外键约束。
@Index
用于给Entity声明一个索引。添加索引通常会使选择操作更快,但会使其他操作变慢,例如插入或更新。
有两种设置Index,用于@ColumnInfo
中或@Entity
中。
通过@Embedded
嵌入到其它实体中的Index,需要重新声明。
默认情况下,父类的Index也不会被继承,需要重新声明,或将子类的inheritSuperIndices设置为true
@ForeignKey
是什么?什么作用?
Dao
数据库访问对象(Data Access Object),定义与数据库交互的查询方法。在Room中,有Query,Delete,Insert三种操作。
@Dao
用于标记dao接口,包含了一系列对数据库对操作。
@Query
用于标记dao中用于查询操作的方法。引用java方法参数的方式是冒号加上参数名:
@Query("SELECT * FROM comments WHERE productId = :productId")
LiveData<List<CommentEntity>> loadComments(int productId);
也可以引用数组,方法如下:
@Query("SELECT * FROM user WHERE uid IN(:userIds)")
public abstract List findByIds(int[] userIds);
该注解支持三种操作:SELECT, UPDATE 和 DELETE。
对于SELECT操作,方法的返回值可以为单独的Java对象,也可以是数组,集合,Cursor和LiveData。如果使用RxJava2,可以返回Flowable<T>或Publisher<T>。
UPDATE和DELETE操作可以返回void或int。int值为该操作影响到的行数。
@Delete
参数必须是被@Entity标记的类或它的集合:
@Dao
public interface MyDao {
@Delete
public void deleteUsers(User... users);
@Delete
public void deleteAll(User user1, User user2);
@Delete
public void deleteWithFriends(User user, List<User> friends);
}
@Insert
参数必须是被@Entity标记的类或它的集合。
Database
数据库的抽象层,持有了众多Dao的引用。
@Database
标记一个被abstract修饰并继承RoomDatabase
的类为Database。
entities:传入所有Entity的class对象;
version:数据库版本号。
exportSchema:设置是否导出数据库schema,默认为true,需要在build.gradle中设置:
android {
...
defaultConfig {
...
javaCompileOptions {
annotationProcessorOptions {
arguments = ["room.schemaLocation":
"$projectDir/schemas".toString()]
}
}
}
}
通过Room.databaseBuilder
或Room.inMemoryDatabaseBuilder
获得该类的实现类:
AppDatabase db = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, AppDatabase.DATABASE_NAME).build();
用法:
db.beginTransaction();
try {
db.productDao().insertAll(products);
db.commentDao().insertAll(comments);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
类型转换
下面的方法将Date对象转换为Long型的时间戳:
public class DateConverter {
@TypeConverter
public static Date toDate(Long timestamp) {...}
...
}
使用@TypeConverters
注解在Database类上声明:
@Database(...)
@TypeConverters(DateConverter.class)
public abstract class AppDatabase extends RoomDatabase {...}