@

# 前言

官方简介:

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. python函数默认值只初始化一次

    当在函数中定义默认值时,值初始化只会进行一次,就是执行到def methodname时执行.看下面代码: from datetime import datetime def test(t=dateti ...

  2. FHD 4K 8K分辨率

    4K(2160P,即4096×2160的像素分辨率)和8K(4320P,即7,680 × 4,320的像素分辨率)属于UHDTV. FHD是FULL HD(Full High Definition)的 ...

  3. 黄衫女子,黄衫好.png

    正想着团队项目中数据该如何解析,就收到了来自软工课程组的一件小黄衫,真是意外之喜.详问其来源,竟是因结对项目做的"较好"而来,顿感受之有愧. 结对项目是两人对文件系统的一个小模拟, ...

  4. chardet模块

    import chardet chardet.detect(f.read())检测哪种编码

  5. 网络协议 SNMP- Windows10无简单SNMP协议服务器配置

    原因:Windwos10 1809后更新版本,无启动SNMP协议服务器可选配置项. 解决: 1.打开设置中的[开发人员模式],设置->更新与安全->开发者选项->开发人员模式 2.添 ...

  6. megacli修复raid1硬盘

    megacli修复raid1硬盘 By HKL, Tuesday 27 August 2019, 评论 [ Hardware Operating ] 使用megaraid修复raid1掉线硬盘 使用说 ...

  7. 010.Python字符串的格式化

    字符串的格式化 顺序传参 索引传参 关键字传参 容器类型传参(列表和元组) {}相当于占位符 1 顺序传参 strvar = "他{}牺牲自己,{}出卖组织" res = strv ...

  8. docker0详解

    docker0:https://blog.csdn.net/kubailing/article/details/87936501 veth pair详解:https://www.cnblogs.com ...

  9. vue项目使用百度地图API获取经纬度

    一.首先在百度api注册获得ak密钥 二.进行引入 (1).第一种方式: 直接在vue中index.html中用script标签引入. //你的ak密钥需要替换真实的你的ak码 <script ...

  10. Runtime PM 处理不当导致的 external abort on non-linefetch 案例分享

    硬件平台:某ARM SoC 软件平台:Linux 1 Runtime PM 简介 在介绍 Runtime PM 之前,不妨先看看传统的电源管理.传统的电源管理机制,称之为 System PM(Syst ...