Android Jetpack組件之Room的介紹與使用(上)

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();
最後參考連接:

郭霖老師的講解: https://mp.weixin.qq.com/s/B1afqgZxHwm3g3eGoi5ATQ

發佈了8 篇原創文章 · 獲贊 37 · 訪問量 8588
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章