JoJo的个人博客

记录精彩的程序人生

目录
Jetpack系列之Room数据库
/    

Jetpack系列之Room数据库

概述

Room作为JetPack组件的一员,可以很好的和LiveData或者Rxjava配合使用。

我使用并封装了JetPack系列组件的用法,java版参考代码JetPackDemo

创建表实体Entity类

@Entity(tableName = "word_table")
public class Word {

   @PrimaryKey
   @NonNull
   @ColumnInfo(name = "word")
   private String mWord;

   public Word(String word) {this.mWord = word;}

   public String getWord(){return this.mWord;}
}
  • 使用@Entity(tableName = "word_table")来标识 数据表的名称,如果Entity()参数为空,会把类名作为表名

  • @PrimaryKey 主键, @PrimaryKey(autoGenerate = true)自增主键

  • @NonNull 不能为空

  • @ColumnInfo(name = "word") 指定表列名

创建Dao层

@Dao
public interface ArticleDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void insert(Article article);

    @Query("select * from article where `id`=:id")
    Article getArticle(String id);

    @Delete
    void delete(Article article);

    @Update(onConflict = OnConflictStrategy.REPLACE)
    void update(Article article);

    //使用LiveData返回,数据库数据改动时,会自动更新LiveData
    @Query("SELECT * from article ORDER BY id ASC")
    LiveData<List<Article>> getAllArticles();
  
    @Query("SELECT * from article ORDER BY id ASC")
    List<Article> getAllArticles();

    @Query("DELETE FROM article")
    void deleteAll();
}
  • 使用@Dao标识这是个Dao
  • onConflict = OnConflictStrategy.IGNORE 设置不同的冲突策略,插入和更新都可以配置
  • 返回结果可以用LiveData包裹,实现数据源的自动更新

添加Room database

@Database

@Database注解标识数据库类文件,可以设置数据库名称,版本号等等配置

@Database(entities = {Article.class}, version = 1, exportSchema = true)

entities设置所有表,version指定版本号,exportSchema是否导出Schema文件,默认为true,需要在build.grale文件中指定导出目录

javaCompileOptions {
    annotationProcessorOptions {
        arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
    }
}

创建数据库的方式

创建一个内存数据库, 但是这种数据库的数据只存在于内存中,也就是进程被杀之后,数据随之丢失

Room.inMemoryDatabaseBuilder()

创建本地数据库

Room.databaseBuilder()

相关配置

允许在主线程进行查询

.allowMainThreadQueries()

数据库创建和打开后的回调

.addCallback(sRoomDatabaseCallback)

设置查询的线程池

.setQueryExecutor()

数据库升级异常之后的回滚

.fallbackToDestructiveMigration()

数据库升级异常后根据指定版本进行回滚

.fallbackToDestructiveMigrationFrom()

升级迁移 升级数据库有结构变化的话,必须要配置这个

.addMigrations(AppDataBase.MIGRATION_1_2)

示例代码

@Database(entities = {Article.class}, version = 1, exportSchema = true)
public abstract class AppDataBase extends RoomDatabase {

    public abstract ArticleDao articleDao();

    private static volatile AppDataBase INSTANCE;

    private static final int NUMBER_OF_THREADS = 4;
    public static final ExecutorService databaseWriteExecutor =
            Executors.newFixedThreadPool(NUMBER_OF_THREADS);

    public static AppDataBase getDatabase() {
        if (INSTANCE == null) {
            synchronized (AppDataBase.class) {
                if (INSTANCE == null) {
//                    创建一个内存数据库, 但是这种数据库的数据只存在于内存中,也就是进程被杀之后,数据随之丢失
//                    Room.inMemoryDatabaseBuilder()
                    INSTANCE = Room.databaseBuilder(MyApplication.instance, AppDataBase.class, "app_database")
//                            //允许在主线程进行查询
//                            .allowMainThreadQueries()
//                            //数据库创建和打开后的回调
                            .addCallback(sRoomDatabaseCallback)
//                            //设置查询的线程池
//                            //.setQueryExecutor()
//                            .openHelperFactory()
//                            //room的日志模式
//                            .setJournalMode()
//                            //数据库升级异常之后的回滚
//                            .fallbackToDestructiveMigration()
//                            //数据库升级异常后根据指定版本进行回滚
//                            .fallbackToDestructiveMigrationFrom()
//                            .addMigrations(AppDataBase.MIGRATION_1_2)
                            .build();
                }
            }
        }
        return INSTANCE;
    }

    static Migration MIGRATION_1_2 = new Migration(1, 2) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {
            database.execSQL("alter table article rename to student");
            database.execSQL("alter table article add column age INTEGER NOT NULL default 0");
            database.execSQL("alter table article add column describe TEXT");
        }
    };

    private static RoomDatabase.Callback sRoomDatabaseCallback = new RoomDatabase.Callback() {
        @Override
        public void onOpen(@NonNull SupportSQLiteDatabase db) {
            super.onOpen(db);
            databaseWriteExecutor.execute(() -> {
                ArticleDao dao = INSTANCE.articleDao();
                dao.deleteAll();
            });
        }
    };
}

创建Repository来使用

public class ArticleRepository {
    private ArticleDao articleDao;
    private LiveData<List<Article>> mAllArticles;

    private static volatile ArticleRepository instance;

    private ArticleRepository() {
        articleDao = AppDataBase.getDatabase().articleDao();
        mAllArticles = articleDao.getAllArticles();
    }

    public static ArticleRepository getInstance() {
        if (instance == null) {
            instance = new ArticleRepository();
        }
        return instance;
    }

    public LiveData<List<Article>> getAllArticles() {
        return mAllArticles;
    }

    public void insert(Article article) {
        AppDataBase.databaseWriteExecutor.execute(() -> articleDao.insert(article));
    }
}

在ViewModel中使用Repository

public class NotificationsViewModel extends BaseViewModel {

    private LiveData<List<Article>> mAllArticles;

    private ArticleRepository mRepository = ArticleRepository.getInstance();

    public NotificationsViewModel() {
        mAllArticles = mRepository.getAllArticles();
    }

    public LiveData<List<Article>> getAllArticles() {
        return mAllArticles;
    }

    void insert(Article article) {
        mRepository.insert(article);
    }

}

参考文档

Android Room with a View - Java


标题:Jetpack系列之Room数据库
作者:SunnySky
地址:https://www.tianyang.pub/articles/2020/07/04/1593850838355.html

评论