在第一篇中我们介绍了基本的使用,包括表的定义、DAO 的定义和使用、简单查询和添加的操作。接着这一篇我们继续看room
在使用过程中的更多操作方法。
上一节中我们的user
中定义有uid
作为主键,在项目中,这个uid
是后台出参,对于每一个用户都是相同的,这时候如果我们直接插入数据这条数据就会报错,因为主键相同。我们可以试一下。
android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: user.uid
这个时候我们就可以在Insert
注解上面增加一个onConflict
参数。这里面REPLACE
代表在主键冲突的时候直接替换。这里还可以使用ABORT
表示终止操作,IGNORE
表示忽略异常,这两种都不会对数据进行修改。
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertAll(vararg users: User)
我们可以通过Update
注解定义更新操作,更新操作中只需要我们传入的对象的主键相同就可以进行更新操作。
@Update
fun updateUser(user: User)
通过Delete
注解定义更新操作,这个操作也是使用主键查询需要删除的实体的。
@Delete
fun delete(user: User)
Query
注解来定义我们使用的查询语句,这个语句也是使用最多,功能最强的语句。我们一个一个学习一下。
我们可以直接使用下面的语句实现查询所有user
表的数据。Query 中的语句对应表中的名称,在编译时候都会进行检查,避免我们查询一些不存在的列数据。
@Query("SELECT * FROM user")
fun getAll(): List<User>
假如需要查询我们数据中所有uid
小于 100 的用户信息,我们可以这样写。
// 传入的 id 通过添加 : 前缀加入到表达式中
@Query("SELECT * FROM user WHERE uid < :id")
fun loadAllUsersLessThan(id: Int): List<User>
// 使用时直接调用
appDatabase.userDao().loadAllUsersLessThan(100)
我们也可以多次使用参数来构建查询语句。
@Query("SELECT * FROM user WHERE first_name LIKE :first AND last_name LIKE :last")
fun findByName(first: String, last: String): List<User>
在我们使用select *
来进行查询的时候,会返回给我们表里面的所有字段数据,如果我们只需要部分字段呢?比如我们只需要姓氏这个字段,那么我们可以定义一个对应的实体类,并在查询是指定我们需要返回的字段即可。
@Query("SELECT first_name, last_name FROM user")
fun loadFullName(): List<NameTuple>
当我们需要查询的限定条件是在一个集合内时,我们可以通过List
或者Array
来定义我们的传入参数,这样Room
在处理时会自动将我们的查询语句展开处理。
@Query("SELECT * FROM user WHERE uid IN (:userIds)")
fun loadAllByIds(userIds: IntArray): List<User>
我们也可以使用连表查询来获取需要多个表结合才会得到的结果。比如我们有三个表,一个用户表,一个书本表,一个借阅记录表,借阅记录表中分别记录借阅的数据 id 和借阅人 id,现在我们需要查询某一个用户借阅的图书集合,我们就可以使用连表查询来实现。
@Query(
"SELECT * FROM book " +
"INNER JOIN loan ON loan.book_id = book.book_id " +
"INNER JOIN user ON user.uid = loan.user_id " +
"WHERE user.first_name LIKE :firstName"
)
fun findBooks(firstName: String): List<Book>
这样我们就基本看完了查询相关的操作,我们借助 Room 也能完成更多的功能了。
文章配套代码地址在码云上,地址连接:https://gitee.com/gitccxx/RoomTestApp