目录

导入依赖

创建一个实体类

定义Dao(实现模糊搜索)

定义DataBase类

调用

效果展示


本文实现的是对单词的模糊搜索。主要是在接口Dao处定义,只有一小段代码,学习过Room数据库的可以直接跳转到那去看。

导入依赖

implementation "androidx.room:room-runtime:2.2.6"annotationProcessor "androidx.room:room-compiler:2.2.6"

创建一个实体类

@Entitypublic class Vocabulary {@PrimaryKey(autoGenerate = true)public long id;@ColumnInfopublic String word;public Vocabulary() {}@Overridepublic String toString() {return word;}}

定义Dao(实现模糊搜索)

这部分也是Room用法中最关键的地方,因为所有访问数据库的操作都是在这里封装的。访问数据库的操作无非就是增删改查这4种,但是业务需求却是千变万化的。而Dao要做的事情就是覆盖所有的业务需求,使得业务方永远只需要与Dao层进行交互,而不必和底层的数据库打交道。
那么下面我们就来看一下一个Dao具体是如何实现的。新建一个UserDao接口,注意必须使用接口,这点和Retrofit是类似的,然后在接口中编写如下代码:

@Daopublic interface VocabularyDao{@Query("SELECT * FROM vocabulary")List getAll();@Query("SELECT * FROM vocabulary WHERE WORD LIKE '%' || :s || '%' ")List searchWords(String s);@Updatevoid upDataWord(Vocabulary vocabulary);@Deletevoid deleteWord(Vocabulary vocabulary);@Insertlong insertWord(Vocabulary vocabulary);}

注意看,实现模糊搜索的语句是这一段

@Query("SELECT * FROM vocabulary WHERE WORD LIKE '%' || :s || '%' ")List searchWords(String s);

注意:

  • '%'是一个字符串,表示一个百分号字符。
  • ||是 SQL 中的字符串拼接运算符,在这里用于将多个字符串连接在一起。
  • :s是一个占位符,表示一个参数,通过方法的参数进行替换。
  • '%'同样是一个字符串,表示另一个百分号字符。

整个表达式的含义是:将一个百分号字符、参数 s、再跟一个百分号字符依次连接在一起,形成一个新的字符串。这样构建出来的字符串可以用作 SQL 查询中的条件语句,完成模糊匹配的功能。

例如,如果传入的参数 s 是 “apple”,那么拼接后的字符串就是 “%apple%”。在 SQL 的 LIKE 条件语句中使用这个字符串,可以匹配包含 “apple” 的任意位置的字符串,实现了模糊搜索的效果。

UserDao接口的上面使用了一个@Dao注解,这样Room才能将它识别成一个Dao。UserDao内部就是根据业务需求对各种数据库操作进行的封装。数据库操作通常有增删改查这4种,因此Room也提供了@Insert、@Delete、@Update和@Query这4种相应的注解。
可以看到,insertUser()方法上面使用了@Insert注解,表示会将参数中传入的User对象插入数据库中,插入完成后还会将自动生成的主键id值返回。updateUser()方法上面使用了@Update注解,表示会将参数中传入的User对象更新到数据库当中。deleteUser()方法上面使用了@Delete注解,表示会将参数传入的User对象从数据库中删除。以上几种数据库操作都是直接使用注解标识即可,不用编写SQL语句。
但是如果想要从数据库中查询数据,或者使用非实体类参数来增删改数据,那么就必须编写SOL语句了。比如说我们在UserDao接口中定义了一个loadAllUsers()方法,用于从数据库中查询所有的用户,如果只使用一个@Query注解,Room将无法知道我们想要查询哪些数据因此必须在@Query注解中编写具体的SQL语句才行。我们还可以将方法中传入的参数指定到SOL语句当中,比如loadUsersolderThan()方法就可以查询所有年龄大于指定参数的用户。另外,如果是使用非实体类参数来增删改数据,那么也要编写SQL语句才行,而且这个时候不能使用@Insert、@Delete或Update注解,而是都要使用@Query注解才行,参考deleteUserByLastName()方法的写法
这样我们就大体定义了添加用户、修改用户数据、查询用户、删除用户这几种数据库操作接口,在实际项目中你根据真实的业务需求来进行定义即可。

定义DataBase类

接下来我们进入最后一个环节:定义Database。这部分内容的写法是非常固定的,只需要定义好3个部分的内容: 数据库的版本号、包含哪些实体类,以及提供Dao层的访问实例。新建一个WordDataBase类,代码如下所示 :

@Database(entities = {Vocabulary.class},version = 1,exportSchema = false)public abstract class WordDataBase extends RoomDatabase {public abstract VocabularyDao vocabularyDao();}

可以看到,这里我们在AppDatabase类的头部使用了Database注解,并在注解中声明了数据库的版本号以及包含哪些实体类,多个实体类之间用逗号隔开即可。
另外,AppDatabase类必须继承自RoomDatabase类,并且一定要使用abstract关键字将它声明成抽象类,然后提供相应的抽象方法,用于获取之前编写的Dao的实例,比如这里提供的userDao()方法。不过我们只需要进行方法声明就可以了,具体的方法实现是由Room在底层自动完成的。

同时,exportSchema@Database 注解中的一个选项,用于指定是否导出数据库的 schema(模式)信息。在 Room Persistence Library 中,schema 是指用于描述数据库结构的文件或者类。

具体来说,如果 exportSchema 设置为 true,Room 会在编译时自动生成一个包含数据库 schema 信息的 JSON 文件,并将其放置在 app module 的 build 目录中。这个 JSON 文件可以用于版本控制和备份,也可以用于 Room 数据库的迁移。但是,在实际开发中,有些时候我们并不需要生成这个 JSON 文件,这时候可以将 exportSchema 设置为 false,避免生成无用的文件,节省空间和时间。

exportSchema = false 表示不导出数据库的 schema 信息,即 Room 不会在编译时生成包含 schema 信息的 JSON 文件。这样可以避免生成无用的文件,提高编译效率。

需要注意的是,如果你使用了 Room 数据库迁移的功能,建议将 exportSchema 设置为 true,以便 Room 自动生成数据库的 schema 信息,方便进行版本控制和迁移操作。

调用

最后在在想要实现的活动中调用即可,代码如下:

WordDataBase = Room.databaseBuilder(getContext(),WordDataBase.class,"my_wordDataBase").build();VocabularyDao dao = wordDataBase.vocabularyDao();

接下来想执行什么操作就执行什么操作,在这里,我主要执行获取数据并实现模糊搜索的操作,具体如下:

new Thread(new Runnable() {@Overridepublic void run() {wordList = dao.getAll();//获取数据库里的消息}}).start();
new Thread(new Runnable() { @Override public void run() { vocabularies = dao.searchWords(newText);//根据关键词进行模糊搜索 }}).start();

注意,由于操作该数据库属于耗时操作,故需要开启线程。

效果展示

该代码实现的一个是contains(),而不是starWith()。