三個部分: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 {...}