@

# 前言

官方简介:

Room 持久性库在 SQLite 的基础上提供了一个抽象层,让用户能够在充分利用 SQLite 的强大功能的同时,获享更强健的数据库访问机制。

引入库:

implementation "androidx.room:room-runtime:2.3.0"
kapt "androidx.room:room-compiler:2.3.0"
//kotlin 扩展库
implementation "androidx.room:room-ktx:2.3.0"

配置 build:

android {
...
defaultConfig {
...
javaCompileOptions {
annotationProcessorOptions {
arguments += mapOf(
"room.schemaLocation" to "$projectDir/schemas",
"room.incremental" to "true",
"room.expandProjection" to "true"
)
}
}
}
}

提示:以下是本篇文章正文内容,下面案例可供参考

一、简单使用

万事开头难, 好记性不如烂笔头. 看十遍不如敲一遍.

所以 咱们先把代码敲起来.

1.Entity

@Entity
class RoomTwoEntity {
@PrimaryKey
var id: String = ""
@ColumnInfo
var nickname: String? = null
@ColumnInfo
var sex: Int = 0 @Ignore
var like = false
}
  • @Entity: 表示数据库中的表
  • @ColumnInfo: 表示table中的字段
  • @Ignore: 表示忽略该字段, (不映射到表中)

细节后面再讲

2.Dao

@Dao
interface RoomTwoDao {
@Query("select * from RoomTwoEntity")
fun get(): MutableList<RoomTwoEntity> @Insert(onConflict = OnConflictStrategy.REPLACE) //当冲突时: ABORT,取消; REPLACE,替换; IGNORE,忽略;
fun add(entity: RoomTwoEntity) @Insert(onConflict = OnConflictStrategy.REPLACE) //当冲突时: ABORT,取消; REPLACE,替换; IGNORE,忽略;
fun addList(list: MutableList<RoomTwoEntity>) @Delete
fun delete(entity: RoomTwoEntity) @Update
fun update(entity: RoomTwoEntity) @Query("delete from RoomTwoEntity where id = :id ") //删除也可以用 query
fun deleteById(id: String)
}

这代码是不是很好阅读!

普通增删改只需要一个注解. 查询需要写 sql

3.DataBase

@Database(entities = [RoomTwoEntity::class], version = 1)
abstract class RoomTestDatabase : RoomDatabase() {
abstract fun roomTwoDao(): RoomTwoDao companion object {
private var instance: RoomTestDatabase? = null
fun getInstance(context: Context): RoomTestDatabase {
if (instance == null) {
instance = Room.databaseBuilder(
context.applicationContext,
RoomTestDatabase::class.java,
"Test.db" //数据库名称
)
// .allowMainThreadQueries() //主线程中执行
.fallbackToDestructiveMigration() //数据稳定前, 重建.
// .addMigrations(MIGRATION_1_2) //版本升级
.build()
}
return instance!!
}
}
}

4.使用

注意: 代码要在子线程中执行. 或者方便测试时打开 .allowMainThreadQueries()

//创建 10 条数据
private fun createTen(){
val list = mutableListOf<RoomTwoEntity>()
repeat(10){
list.add(RoomTwoEntity().apply {
id = "room$it"
nickname = "名字$it"
})
}
RoomTestDatabase.getInstance(mActivity).roomTwoDao().addList(list)
} //查询数据
private fun query(): MutableList<RoomTwoEntity>{
return RoomTestDatabase.getInstance(mActivity).roomTwoDao().get()
} //例如
GlobalScope.launch(Dispatchers.IO) {
createTen()
}

二、参数解析

1.Entity

1.1 @Entity

字段名 意义用法
tableName (String) table名, 默认Entity类名.
indices (Index[]) 索引, 搞过数据库的都懂吧.
单列:indices = arrayOf(Index(value = ["last_name"]))
多列:indices = arrayOf(Index(value = ["last_name", "address"]))
多个索引:indices = arrayOf(Index(value = ["last_name"]),Index(value = ["address"]))
Index.unique = true 索引项唯一
inheritSuperIndices (boolean) 是否继承父类的索引
primaryKeys (String[]) 主键. 单主键的时候可以定义在字段上. 复合主键的时候定义在类上.
它应该也能定义父类的字段.
示例: primaryKeys = arrayOf("firstName", "lastName")
foreignKeys 外键
ignoredColumns (String[]) 忽略字段, 更容易的忽略父类字段

1.2 @ColumnInfo

这个注解默认可以省略

字段名 意义用法
name 列名, 默认就是属性名
typeAffinity 字段类型, 默认按属性类型自动生成. 还有 TEXT,INTEGER,REAL,BLOB
index (boolean) 是否生成单列索引, 默认false
collate 建表时 列的排序
defaultValue 列的默认值

1.3 @PrimaryKey

主键必须有, 且必须注解标出

每个实体必须将至少 1 个字段定义为主键。即使只有 1 个字段,您仍然需要为该字段添加 @PrimaryKey 注释。此外,如果您想让 Room 为实体分配自动 ID,则可以设置 @PrimaryKey 的 autoGenerate 属性。如果实体具有复合主键,您可以使用 @Entity 注释的 primaryKeys 属性.

2.Dao

2.1 onConflict

@Insert @Update 时:

新增或修改时, 假设与原有行数据冲突(例如主键冲突). 时的处理方式

用法
OnConflictStrategy.REPLACE 覆盖,替换 原有数据
OnConflictStrategy.ABORT (默认模式) 严格模式, 会让事务失败并回滚
OnConflictStrategy.IGNORE 非严格模式, 会忽略冲突行, 然后继续执行其他操作

2.2 还可以这样用:

@Dao
interface MyDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertUsers(vararg users: User) // java: (User... users) @Insert
fun insertBothUsers(user1: User, user2: User) //多实体 @Insert
fun insertUsersAndFriends(user: User, friends: List<User>) @Update
//可以让它返回一个 Int, 代表数据库中更新的行数
fun updateUsers(vararg users: User): Int @Delete
fun deleteUsers(vararg users: User): Int //返回行数
}

2.3 @Query

以下搬运自官方文章:

@Query 是 DAO 类中使用的主要注释。它允许您对数据库执行读/写操作。每个 @Query 方法都会在编译时进行验证,因此如果查询出现问题,则会发生编译错误,而不是运行时失败。

Room 还会验证查询的返回值,以确保当返回的对象中的字段名称与查询响应中的对应列名称不匹配时,Room 可以通过以下两种方式之一提醒您:

  • 如果只有部分字段名称匹配,则会发出警告。
  • 如果没有任何字段名称匹配,则会发出错误。

3.查询方式

它可以这样查: 冒号后写参数名.

@Query("SELECT * FROM user WHERE age > :minAge")
fun loadAllUsersOlderThan(minAge: Int): Array<User>

也可以这样查: 只查部分字段

@Query("SELECT first_name, last_name FROM user")
fun loadFullName(): List<NameTuple>

还可以这样查: 传入参数集合

@Query("SELECT first_name, last_name FROM user WHERE region IN (:regions)")
fun loadUsersFromRegions(regions: List<String>): List<NameTuple>

更可以这样查: 连表查询,复杂查询等

@Query(
"SELECT user.name AS userName, pet.name AS petName " +
"FROM user, pet " +
"WHERE user.id = pet.user_id"
)
fun loadUserAndPetNames(): LiveData<List<UserPet>> // You can also define this class in a separate file.
data class UserPet(val userName: String?, val petName: String?)

虽然博主没测, 但这里 UserPet 估计是不需要 @Entity 的;

开启事务

@Transaction

@Dao
abstract class UsersDao {
@Transaction
open suspend fun setLoggedInUser(loggedInUser: User) {
deleteUser(loggedInUser)
insertUser(loggedInUser)
} @Query("DELETE FROM users")
abstract fun deleteUser(user: User) @Insert
abstract suspend fun insertUser(user: User)
}

因为DB操作必须要在子线程:

可以将 suspend Kotlin 关键字添加到 DAO 方法中,以使用 Kotlin 协程功能使这些方法成为异步方法。这样可确保不会在主线程上执行这些方法。

就写到这把, 篇幅有点长了, 剩下的下一篇再讲.

总结

room的使用可比直接用SQLite简单多了. 而且方便升级. 还能够配合Paging, 配合LiveData, FLow等使用.

上一篇: Paging3-分页数据加载库(结合room)

下一篇: Room-数据持久化存储(进阶)

Room-数据持久化存储(入门)的更多相关文章

  1. iOS数据持久化存储:归档

    在平时的iOS开发中,我们经常用到的数据持久化存储方式大概主要有:NSUserDefaults(plist),文件,数据库,归档..前三种比较经常用到,第四种归档我个人感觉用的还是比较少的,恰恰因为用 ...

  2. iOS开发——数据持久化Swift篇&使用Core Data进行数据持久化存储

    使用Core Data进行数据持久化存储   一,Core Data介绍 1,Core Data是iOS5之后才出现的一个数据持久化存储框架,它提供了对象-关系映射(ORM)的功能,即能够将对象转化成 ...

  3. Swift - 使用Core Data进行数据持久化存储

    一,Core Data介绍 1,Core Data是iOS5之后才出现的一个数据持久化存储框架,它提供了对象-关系映射(ORM)的功能,即能够将对象转化成数据,也能够将保存在数据库中的数据还原成对象. ...

  4. vuex数据持久化存储

    想想好还是说下vuex数据的持久化存储吧.依稀还记得在做第一个vue项目时,由于刚刚使用vue,对vue的一些基本概念只是有一个简单的了解.当涉及到非父子组件之间通信时,选择了vuex.只是后来竟然发 ...

  5. [Xcode 实际操作]七、文件与数据-(14)数据持久化存储框架CoreData的使用:删除CoreData中的数据

    目录:[Swift]Xcode实际操作 本文将演示如何删除数据持久化对象. 在项目导航区,打开视图控制器的代码文件[ViewController.swift] import UIKit //引入数据持 ...

  6. [Xcode 实际操作]七、文件与数据-(13)数据持久化存储框架CoreData的使用:编辑CoreData中的数据

    目录:[Swift]Xcode实际操作 本文将演示如何修改数据持久化对象. 在项目导航区,打开视图控制器的代码文件[ViewController.swift] import UIKit //引入数据持 ...

  7. [Xcode 实际操作]七、文件与数据-(12)数据持久化存储框架CoreData的使用:查找CoreData中的数据

    目录:[Swift]Xcode实际操作 本文将演示如何查找数据持久化对象. 在项目导航区,打开视图控制器的代码文件[ViewController.swift] import UIKit //引入数据持 ...

  8. [Xcode 实际操作]七、文件与数据-(11)数据持久化存储框架CoreData的使用:创建CoreData实体并插入数据

    目录:[Swift]Xcode实际操作 本文将演示[CoreData]数据持久化存储框架的使用. 点击[Create a new Xcode project]创建一个新的项目 ->[Single ...

  9. 转载 -- iOS数据持久化存储

    作者:@翁呀伟呀 授权本站转载 概论 所谓的持久化,就是将数据保存到硬盘中,使得在应用程序或机器重启后可以继续访问之前保存的数据.在iOS开发中,有很多数据持久化的方案,接下来我将尝试着介绍一下5种方 ...

  10. iOS数据持久化存储之属性列表

    属性列表(plist) iOS提供了一种plist格式的文件(属性列表)用于存储轻量级的数据,属性列表是一种XML格式的文件,拓展名为plist.如果对象是NSString.NSDictionary. ...

随机推荐

  1. 关于MySQL参数,这些你要知道

    前言: 在前面一些文章中,经常能看到介绍某某参数的作用,可能有些小伙伴仍搞不清楚 MySQL 参数是啥.本篇文章我们来聊聊 MySQL 参数,学习下如何管理维护 MySQL 参数. 1.MySQL参数 ...

  2. MindSpore模型验证

    技术背景 在前面一篇博客中,我们介绍了MindSpore在机器学习过程中保存和加载模型的方法.这种将模型存储为静态文件的做法,使得我们可以更灵活的使用训练出来的模型,比如用于各种数据集的验证,或者是迁 ...

  3. [Django框架之路由层匹配、有名 无名分组、反向解析、路由分发、名称空间、伪静态、本地虚拟环境、django版本区别]

    [Django框架之路由层匹配.有名 无名分组.反向解析.路由分发.名称空间.伪静态.本地虚拟环境.django版本区别] 路由层 路由即请求地址与视图函数的映射关系,如果把网站比喻成一本书,那路由就 ...

  4. 剑指offer 数组中的重复数字

    问题描述: 在长度为n的数组中,所有的元素都是0到n-1的范围内. 数组中的某些数字是重复的,但不知道有几个重复的数字,也不知道重复了几次,请找出任意重复的数字. 例如,输入长度为7的数组{2,3,1 ...

  5. .Net·快速查找哪一个类库引用了哪一个Package

    阅文时长 | 0.18分钟 字数统计 | 348.8字符 主要内容 | 1.引言&背景 2.查找法示例 3.声明与参考资料 『.Net·快速查找哪一个类库引用了哪一个Package』 编写人 ...

  6. [bug] Authentication failed for token submission (认证失败)异常

    原因 gitee上下的项目,启动后能访问首页,但登录报错.原因是根据用户名上数据库查密码没有得到结果,中间任何环节有问题都可能导致,我的是因为mapper.xml中的<mapper namesp ...

  7. [bug] Docker:Error ruuning deviceCreate(createSnapDevice) dm_task_run failed

    原因 删除容器时报错,元信息出错,需要修复 最后一个参数要改成自己docker元信息路径,如: thin_check --clear-needs-check-flag /var/lib/docker/ ...

  8. [rhel-media] :Yum软件仓库唯一标识符,避免与其他仓库冲突。

    第1步:进入到/etc/yum.repos.d/目录中(因为该目录存放着Yum软件仓库的配置文件). 第2步:使用Vim编辑器创建一个名为rhel7.repo的新配置文件(文件名称可随意,但后缀必须为 ...

  9. Play-book格式写法

    Play-Book playbook的组成 play 角色(主机或者主机组) task 任务,演戏的动作 总结:playbook是有多个play组成,一个play有多个task:剧本由一个或者多个演员 ...

  10. (转)Linux下用户组、文件权限详解

    转自https://www.cnblogs.com/123-/p/4189072.html 用户组 在linux中的每个用户必须属于一个组,不能独立于组外.在linux中每个文件有所有者.所在组.其它 ...