@

# 前言

官方简介:

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. 2020.12.20vj补题

    A - Insomnia cure 题意:一共s只龙,每隔k,l,m,n只龙就会受伤,问这s只龙有多少龙是受伤的 思路:看起来题目范围并不是很多,直接进行循环判断 代码: 1 #include< ...

  2. c#基于supersocket的简单websocket服务端收发消息实现

    using log4net; using SuperSocket.SocketBase; using SuperSocket.WebSocket; using System; using System ...

  3. nginx日志文件按天记录定时清理循环记录

    问题 nginx日志默认记录在一个文件access.log中,时间长了会导致日志文件特别大,甚至磁盘占满. 解决方案 使用以下方法,将access.log文件每天一个,然后清过15天以前的文件. 方法 ...

  4. 向Vertex Shader传递vertex attribute

    在VBO.VAO和EBO那一节,介绍了如何向Vertex Shader传递vertex attribute的基本方法.现在我准备把这个话题再次扩展开. 传递整型数据 之前我们的顶点属性数据都是floa ...

  5. 21.File和IO流

    IO就可以对文件进行读写 File表示要读写的文件在哪,也可以对文件进行创建,删除等操作 小结: IO流是什么? 1.可以将数据从本地文件中读取出来 2.可以将数据从内存保存到本地文件 File类时什 ...

  6. [Java] Spring 原理

    IOC(Inverse of Control)控制反转 依赖对象的获得被反转了,由自己创建变为从IOC容器获取 优点 代码更简介,不需要new对象 面向接口编程,使用者与具体类解耦,易扩展 方便进行A ...

  7. 用nvm的方式安装node

    一.nvm简介 Node Version Manager(Node版本管理工具)由于以后的开发工作可能会在多个Node版本中测试,而且Node的版本也比较多,所以需要这么款工具来管理.   nvm的安 ...

  8. [Linux] Linux C编程一站式学习 Part.3

    Linux系统编程 文件与I/O C标准I/O库函数与Unbuffered I/O函数 C标准I/O库函数printf().putchar().fputs(),会在用户空间开辟I/O缓冲区 系统函数o ...

  9. Sql Server 课堂笔记

    创建表 --创建学生表 create table student (sno char(8) primary key, sname char(8) not null unique, ssex char( ...

  10. C++知识点案例 笔记-2

    1.友元函数 2.友元类 3.继承(公有继承) 4.公有继承的访问权限 5.私有继承的访问权限 6.保护继承的访问权限(两次继承) ==友元函数== #include <iostream> ...