Android Jetpack(五)Room

一、Room 介绍

        Room 是一个对象关系映射(ORM)库Room 抽象了 SQLite 的使用,可以在充分利用 SQLite 的同时访问流畅的数据库。按照官方的话说,Room 持久性库在 SQLite 的基础上提供了一个抽象层,让用户能够在充分利用 SQLite 的强大功能的同时,获享更强健的数据库访问机制。

        Room 本质上是一个 ORM 库,里面用了大量注解,一般配合 Jetpack 其他组件一起使用。

        Room由三个重要的组件组成:Database、Entity、DAO

(1)Database数据库持有者,并充当与应用程序持久化的、关系型的数据的底层连接的主要访问点。通常情况下,一个应用只需要一个 Database 类,为了防止资源消耗,通常使用单例模式创建 Database 类。

        使用 @Database 注释的类应满足以下条件:

  • 继承了 RoomDatabase 的抽象类
  • 在注解中包含与数据库相关联的实体类列表
  • 包含一个无参抽象方法,并返回使用 @Dao 注释的类。 在运行时,你可以通过调用 Room.databaseBuilder()Room.inMemoryDatabaseBuilder()来获取 Database 实例

(2)Entity:实体,与SQLite数据库中的表是一一对应的。

(3)DAO(Data Access Object):数据访问对象包含数据库访问的各种接口

        Room 组件关系图如下:

        

        应用程序使用 Room 数据库来获取与该数据库关联的数据访问对象(DAO)。然后,应用程序使用每个 DAO 从数据库中获取实体,并将对这些实体的任何更改保存回数据库。最后,应用程序使用实体来获取和设置与数据库中的表列对应的值。

二、Repository 简介

        通常我们在使用 Room 时,通常会在 数据库调用者 DAO 之间再增加一层 Repository。

        Repository 不是 Room 数据库体系结构的组件,但是建议在项目中创建 Repository。Repository 为数据库访问提供了一个干净的 API。

        Repository 的主要作用是提供不同的数据访问策略。在最常见的示例,Repository 实现了用于决定是从网络获取数据还是使用在本地数据库中缓存的结果的逻辑,既避免了 ViewModel 和数据的直接交互,又统一了单一真实数据源的逻辑

        

        Repository 在 MVVM 架构中的位置:

        

 三、Room 使用

1. 添加依赖

implementation 'androidx.room:room-runtime:2.2.3'
annotationProcessor 'androidx.room:room-compiler:2.2.3'
androidTestImplementation 'androidx.room:room-testing:2.2.3'

2. 定义实体类

@Entity:注解标识创建表,使用@Entity(tableName = "users")自定义表名

  • indices:对特定的field建立索引加速数据库访问                                                                                                                索引:@Entity(indices = @Index("name"))                                                                                                                      复合索引:@Entity(indices = @Index(value = {"last_name", "address"}))
  • ignoredColumns:对特定的属性进行忽略      @Entity(ignoredColumns = "picture")


@PrimaryKey:注解表示为主键,使用@Entity(primaryKeys = {"firstName", "lastName"})表示复合主键,使用@PrimaryKey(autoGenerate = true):设置主键自且类型为INTEGER
@ForeignKey用于设置外键@Entity(foreignKeys = @ForeignKey(entity = User.class, parentColumns = "id",childColumns = "user_id"))

@ColumnInfo:注解标识数据库列,使用@ColumnInfo(name = "last_name")自定义列名

@Ignore:注解表示忽略此对象,数据库中不会创建此列;若使用继承,忽略父类的一个对象

@NonNull:非空

例如:

@Entity
public class Word {
    @PrimaryKey(autoGenerate = true)
    public int id;

    @ColumnInfo(name = "english_word")
    public String englishWord;
    @ColumnInfo(name = "chinese_meaning")
    public String chineseMeaning;
    @Ignore
    boolean chineseInvisible;
}

3. 编写DAO接口

@Dao:注解是一个数据访问对象
 

@Insert:注解为插入

@Update:注解为更新

@Delete:注解为删除
注意:使用条件删除,不能通过@Delete去做,可以使用@Query('sql')去执行。

@Query:注解为查询

@Dao
public interface WordDao {
    @Insert
    void insertWords(Word... words);

    @Update
    void updateWords(Word... words);

    @Delete
    void deleteWords(Word... words);

    @Query("DELETE FROM WORD")
    void deleteAllWords();

    @Query("SELECT * FROM WORD ORDER BY ID DESC")
    List<Word> getAllWords();

    @Query("SELECT * FROM WORD ORDER BY ID DESC")
    LiveData<List<Word>> getAllWordsLive();

    @Query("SELECT * FROM WORD WHERE english_word LIKE :pattern ORDER BY ID DESC")
    LiveData<List<Word>> findWordsWithPattern(String pattern);  //模糊查询
}

 4. 创建Database

@Database: Database对应的对象(RoomDatabase)必须添加,包含如下属性:

  • entities: 数据库相关的所有Entity实体类,他们会转化成数据库里面的表
  • version:数据库版本
  • exportSchema: 是否把Schema导出到文件夹中,默认true
@Database(entities = {Word.class}, version = 2, exportSchema = false)
public abstract class WordDatabase extends RoomDatabase {
    //单例模式:减少频繁创建所造成的资源消耗
    private static WordDatabase INSTANCE;

    public static synchronized WordDatabase getInstance(Context context) {
        if (INSTANCE == null) {
            INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
                    WordDatabase.class, "word_database")
//                    .allowMainThreadQueries()  //允许在主线程中执行
//                    .fallbackToDestructiveMigration()  //不添加任何迁移策略,破坏式迁移:将现有的数据清空
                    .addMigrations(MIGRATION_1_2)
                    .build();
        }
        return INSTANCE;
    }

    public abstract WordDao getWordDao();

    //迁移策略
    private static final Migration MIGRATION_1_2 = new Migration(1, 2) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {
            database.execSQL("ALTER TABLE WORD ADD COLUMN chinese_invisible INTEGER NOT NULL DEFAULT 0");
        }
    };
}
发布了67 篇原创文章 · 获赞 69 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_34519487/article/details/104340068