1.Room是什麼
Room是Google 在2017年的IO大會上推出的基於SQLite的ORM數據庫框架。通過註解的方式來進行數據庫的配置,以及SQL的查詢, 並且在編譯的過程中,會檢查SQL以及數據庫配置等的正確性,同時也支持外鍵、事務等,
谷歌Room介紹:https://developer.android.google.cn/topic/libraries/architecture/room#blogs
2.爲什麼會選擇Room?
因爲Room有下面幾個優點:
① SQL查詢在編譯時就會驗證 - 在編譯時檢查每個@Query和@Entity等,這就意味着沒有任何運行時錯誤的風險可能會導致應用 程序崩潰(並且它不僅檢查語法問題,還會檢查是否有該表)
② 較少的模板代碼
③ 與 LiveData集成
個人觀點:Room相比GreenDao而言是官方推薦的一個關於數據庫的依賴庫,Room更需要開發人員有較專業的SQL數據庫知識,
它涉及到SQL的語法編寫和SQL數據庫的升級,如果對SQL語法不懂的開發者來說,使用起來是很有難度的,
但對於熟悉SQL語法的開發者來說,用起來比GreenDao好用許多
3.Room有3個主要構件:
Entity: 表示數據庫內的表(實體類).
Dao: 包含用於訪問數據庫的方法.
Database: 包含了數據庫持有者, 並對於連接應用上持久化的相關數據, 作爲一個主要的訪問點來服務.
註解了@Database的類應該滿足以下條件:
繼承了RoomDatabase的抽象類;
包含實體列表, 而這些實體與該註解之下數據庫關聯;
包含一個抽象方法, 無參且返回一個註解了@Dao的類;
這三個組件之間的關係如下圖:
3.1Entry:(實體類)
每個Entity代表數據庫中某個表的實體類。
默認情況下Room會把Entity裏面所有的字段對應到表上的每一列。
如果需要制定某個字段不作爲表中的一列需要添加@Ignore註解。
@Entity(tableName="WordsBean")
public class WordsBean {
@PrimaryKey(autoGenerate = true)
private int id;
@ColumnInfo(name = "Chinese_name")
private String chinese;
private String english;
@Ignore
private boolean isShow;
}
比如上面的isShow字段代碼因爲使用了@Ignore所以該字段不會映射到WordsBean表中(WordsBean表中不會產生該列數據)。
要持久化一個字段,Room必須有機會進入它。你可以把一個字段公開,或者你可以爲它提供一個getter和setter方法。
如果使用getter和setter方法,請記住它們是基於Room中的JavaBeans約定。
注意:實體可以有空構造函數(如果相應的DAO類可以訪問每個持久化字段)或其參數包含與實體中字段匹配的類型和名稱的構造函數。
Room也可以使用全部或部分構造函數,例如只接收一些字段的構造函數。
@Entity註解包含的屬性有:
tableName:設置表名字。默認是類的名字。
indices:設置索引。
inheritSuperIndices:父類的索引是否會自動被當前類繼承。
primaryKey:設置主鍵。
foreignKeys:設置外鍵。
ColumnInfo :設置列的名字,默認是字段的名字
3.2、DAO(數據訪問對象)
這個組件代表了作爲DAO的接口。DAO是Room的主要組件,負責定義訪問數據庫的方法。
Room使用過程中一般使用抽象DAO類來定義數據庫的CRUD操作。DAO可以是一個接口也可以是一個抽象類。
如果它是一個抽象類,它可以有一個構造函數,它將RoomDatabase作爲其唯一參數。Room在編譯時創建每個DAO時。
3.2.1、Insert(插入/增加)
當DAO裏面的某個方法添加了@Insert註解。Room會生成一個實現,將所有參數插入到數據庫中的一個方法。
有時插入數據和更新數據會產生衝突,所以就有了衝突之後要怎麼解決,SQLite對於事務衝突定義了5個方案:
1. replace:見名知意,替換,違反的記錄被刪除,以新記錄代替之(默認狀態)
2.ignore: 違反的記錄保持原貌,其它記錄繼續執行
3.fail: 終止命令,違反之前執行的操作得到保存
4.abort 終止命令,恢復違反之前執行的修改
5.rollback 終止命令和事務,回滾整個事務
@Dao
public interface WordsDao {
@Insert(onConflict=OnConflictStrategy.REPLACE )
void insertWords(WordsBean... wordsBeans);
}
注:插入的類型後加三個點表示可以傳入wordsbean,也可傳入wordsBean的數組
3.2.2、Update(修改)
@Update註解在數據庫中用於修改一組實體的字段。它使用每個實體的主鍵來匹配查詢。
@Dao
public interface WordsDao {
@Update
void updateWords(WordsBean... wordsBeans);
}
@Update註解的方法也可以返回int變量。表示修改了多少條數據
3.2. 3.Delete(刪除)
用於從數據庫中刪除給定參數的一系列實體,它使用主鍵匹配數據庫中相應的數據
@Dao
public interface WordsDao {
@Delete
void deleteWords(WordsBean... wordsBeans);
}
3.2.4.Query(查詢)
查詢數據庫中的數據,可以根據任意條件查詢,它允許您對數據庫執行讀/寫操作.
@Dao
public interface WordsDao {
@Query("SELECT * FROM WordsBean")
LiveData<List<WordsBean>> selectAll();
}
3.2.5、Room數據庫支持各種SQL語句例如
@Dao
public interface WordsDao {
/*單條刪除*/
@Query("DELETE FROM WordsBean where id=:id")
void deleteWords(Integer[] id);
/*查詢全部*/
@Query("SELECT * FROM WordsBean")
LiveData<List<WordsBean>> selectAll();
/*刪除全部*/
@Query("DELETE FROM WordsBean")
void clearAll();
/*模糊查詢*/
@Query("SELECT * FROM WordsBean WHERE chinese LIKE '%' || :name || '%'")
List<WordsBean> selectLike(String[] name);
}
4、Database(數據庫)
@Database註解可以用來創建數據庫的持有者。該註解定義了實體列表,該類的內容定義了數據庫中的DAO列表,必須繼承RoomDatabase
Database對應的對象(RoomDatabase)必須添加@Database註解,@Database常用的註解有
1.entities:數據庫相關的Entity實體類(可以傳入多個Entity,至少傳入一個相關的Entity實例),他們會轉化成數據庫裏面的表。
2.version:數據庫版本。
獲取Database對象:在運行時,你可以通過調用Room.databaseBuilder()或者Room.inMemoryDatabaseBuilder()獲取實例,
因爲每次對數據庫進行操作都需要用到Database對象,所以一般都會將Database設計成單例,來減少對內存的消耗,
一般在Appliaction類中或Database中創建
兩種方式獲取Database對象的區別:
Room.databaseBuilder():生成Database對象,並且創建一個存在文件系統中的數據庫。
Room.inMemoryDatabaseBuilder():生成Database對象並且創建一個存在內存中的數據庫。當應用退出的時候(應用進程關閉)數據庫也消失。
@Database(entities = {WordsBean.class}, version = 1)
public abstract class WordsDataBase extends RoomDatabase {
private static WordsDataBase dataBase;
public static synchronized WordsDataBase getInstance(Context mContext) {
if (dataBase == null) {
dataBase = Room.databaseBuilder(mContext.getApplicationContext(), WordsDataBase.class, "db_words")
//.allowMainThreadQueries()
//不允許在主線程對數據庫進行操作,爲了方便測試可以加入該方法強行允許在主線程進行CURD操作
.build();
}
return dataBase;
}
public abstract WordsDao getWordsDao();
}
對於數據庫一般不允許在主線程進行CURD操作,所以一般Room數據庫都是在RxJava或者AsyncTask的配合下使用,不過爲了方便測試可以在獲取Database實例時, 加上allowMainThreadQueries()強行允許在主線程進行CURD操作.
5、總結:
Room數據庫框架的基本使用基本分爲以下四個步驟:
1.添加Room依賴:
def room_version = "1.1.1"
implementation "android.arch.persistence.room:runtime:$room_version"
annotationProcessor "android.arch.persistence.room:compiler:$room_version"
2.建立好Room數據庫 (Entity , Database ,Dao)
3.獲取Dao對象 例如 :WordsDao wordsDao = WordsDataBase.getInstance(application).getWordsDao();
4.通過Dao對象對數據庫進行CURD操作 例如: List<WordsBean> listData = wordsDao.selectAll();