@

# 前言

官方简介:

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. 看雪加密解密第一个traceme程序破解

    工具:ollydbg(吾爱破解2.10版) 工具设置:因为traceme是一个win32图形用户程序,所以其程序入口点在WinMain()函数处,设置ollydbg的调试设置的事件选项,选中在WinM ...

  2. SprintBoot使用Validation

    1.为什么要使用Validation 在开发过程中有没有使用一堆的if来判断字段是否为空.电话号码是否正确.某个输入是否符合长度等对字段的判断.这样的代码可读性差,而且还不美观,那么使用Validat ...

  3. [前端、HTTP协议、HTML标签]

    [前端.HTTP协议.HTML标签] 什么是前端 """ 任何与用户直接打交道的操作界面都可以称之为前端 比如:电脑界面 手机界面 平板界面 什么是后端 后端类似于幕后操 ...

  4. 适用于windows10 Linux子系统的安装管理配置 How To Management Windows Subsystem for Linux WSL

    什么是WSL Windows Subsystem for Linux 简称WLS,适用于Linux的Windows子系统,可以直接在Windows上运行Linux环境(包括大部分命令行工具) Linu ...

  5. [OS] 概述&学习资料

    计算机启动 启动自检 初始化启动 启动加载 内核装载 登录 中断 硬件中断 I/O设备 CPU Timer:时间片结束后,发中断给CPU Scheduler:将CPU合理分配任务使用 异常中断 内存: ...

  6. 烽火SATA SSD DSS200-B

    烽火SATA SSD DSS200-B 运营商用户 > 产品与解决方案 > 产品 烽火SATA SSD DSS200-B 烽火通信 DSS200-B 2.5" SATA SSD ...

  7. 【CentOS_7】使用tcpdump抓明文包

    tcpdump port 12345 -X -X:以十六进制与ASCII方式输出,用于抓取http等明文传输协议 tcpdump功能强大,更多参数可以参考  https://www.cnblogs.c ...

  8. 实例:使用playbook实现httpd安装、配置、以及虚拟主机的配置

    一.安装环境配置 1.在控制节点给受控主机配置本地仓库文件 [root@ansible ~]# vim /etc/yum.repos.d/dvd.repo [AppStream] name=appst ...

  9. linux各文件夹的作用-(转自玉米疯收)

    linux下的文件结构,看看每个文件夹都是干吗用的 /bin 二进制可执行命令 /dev 设备特殊文件 /etc 系统管理和配置文件 /etc/rc.d 启动的配置文件和脚本 /home 用户主目录的 ...

  10. 网上的说TB6560存在的问题

    https://www.amobbs.com/thread-5506456-2-1.html