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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章