android ROOM kotlin官方文档完全学习2.6

使用 Room 将数据保存到本地数据库 | Android Developers (google.cn)

一、简介

1.1 引入
dependencies {def room_version = "2.6.1"implementation "androidx.room:room-runtime:$room_version"//如下三选一annotationProcessor "androidx.room:room-compiler:$room_version"kapt "androidx.room:room-compiler:$room_version"ksp "androidx.room:room-compiler:$room_version"// optional - RxJava2 support for Roomimplementation "androidx.room:room-rxjava2:$room_version"// optional - RxJava3 support for Roomimplementation "androidx.room:room-rxjava3:$room_version"// optional - Guava support for Room, including Optional and ListenableFutureimplementation "androidx.room:room-guava:$room_version"// optional - Test helperstestImplementation "androidx.room:room-testing:$room_version"// optional - Paging 3 Integrationimplementation "androidx.room:room-paging:$room_version"
}
1.2 三大组件
  • DataBase,用于保存数据库并作为应用持久性数据底层连接的主要访问点。
  • Entity,用于表示应用的数据库中的表。
  • DAO(数据访问对象),为您的应用提供在数据库中查询、更新、插入和删除数据的方法。
1.3 快速示例
1.3.1 定义User类

定义User数据实体。每个实例代表数据库user表的一行。

@Entity
data class User(@PrimaryKey val uid: Int,@ColumnInfo(name = "first_name") val firstName: String?,@ColumnInfo(name = "last_name") val lastName: String?
)

详细使用参考第二章【使用Room实体定义数据】。

1.3.2 数据访问对象(DAO)

用来操控user表的数据交互的方法。

@Dao
interface UserDao {@Query("SELECT * FROM user")fun getAll(): List<User>@Query("SELECT * FROM user WHERE uid IN (:userIds)")fun loadAllByIds(userIds: IntArray): List<User>@Query("SELECT * FROM user WHERE first_name LIKE :first AND " +"last_name LIKE :last LIMIT 1")fun findByName(first: String, last: String): User@Insertfun insertAll(vararg users: User)@Deletefun delete(user: User)
}

详细使用参考第三章【使用DAO访问数据】。

1.3.3 数据库

作为应用对持久性数据的主要访问点。几个条件如下:

  • 使用@Database注解,列出所有的entities。

  • 必须抽象类,继承自RoomDatabase。

  • 每一个DAO类,都需要一个定义一个零参数的抽象函数,返回DAO类的实例。

@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {abstract fun userDao(): UserDaocompanion object {private var instance:AppDatabase? = nullprivate const val DATA_BASE_NAME = "app"private val lock = Any()/*** 调用单例数据库*/val db : AppDatabaseget() {if (instance == null) {synchronized(lock) {if (instance == null) {instance = Room.databaseBuilder(Globals.app,AppDatabase::class.java,DATA_BASE_NAME)//.enableMultiInstanceInvalidation() 多进程启用 todo.build()}}}return instance!!}}
}//使用的方法:
val userDao = AppDatabase.db().userDao()
val users: List<User> = userDao.getAll()

二、使用 Room 实体定义数据

2.1 实体详解(@Entity, tableName)
@Entity(tableName = "users")
data class User(@PrimaryKey val id: Int,val firstName: String?,val lastName: String?
)

必须是public或者有get,set函数。定义为每一列。

类名就是就是数据表名,可以通过@entity里面的tableName修改。

字段名可以通过ColumnInfo的name修改。

表和列名都不区分大小写。

2.2 主键(@PrimaryKey, autoGenerate)

必须定义主键,并使用@PrimaryKey注解。

@PrimaryKey val id: Int

由于默认是@PrimaryKey(autoGenerate = false)是false,所以必须自行管理id的唯一性,所以一般情况,我们需要设置为true。

2.3 复合主键(@Entity primaryKeys)
@Entity(primaryKeys = ["firstName", "lastName"])
data class User(val firstName: String?,val lastName: String?
)

如果您需要通过多个列的组合对实体实例进行唯一标识,则可以通过列出@Entity primaryKeys属性中的以下列定义一个复合主键。

2.4 忽略字段(@Ignore,@Entity ignoredColumns)
@Entity
data class User(@PrimaryKey val id: Int,val firstName: String?,val lastName: String?,@Ignore val picture: Bitmap?
)

如果是继承,想忽略父类里面的字段,通过@Entity(ignoredColumns = [ ])处理:

open class User {var picture: Bitmap? = null
}@Entity(ignoredColumns = ["picture"])
data class RemoteUser(@PrimaryKey val id: Int,val hasVpn: Boolean
) : User()

三、使用DAO访问数据

可以定义为接口或者抽象类。使用@Dao进行注解。示例:

@Dao
interface UserDao {@Insertfun insertAll(vararg users: User)@Deletefun delete(user: User)@Query("SELECT * FROM user")fun getAll(): List<User>
}

有2种方式定义函数:

  • 3.1 不用编写SQL代码,实现插入更新删除数据库的行。
  • 3.2 自行编写SQL查询
3.1 便捷方法
Insert
@Dao
interface UserDao {@Insert(onConflict = OnConflictStrategy.REPLACE) //遇到有数据就替换,可以选择ABORT,IGNOREfun insertUsers(vararg users: User)@Insertfun insertBothUsers(user1: User, user2: User)@Insertfun insertUsersAndFriends(user: User, friends: List<User>)
}

自己可以追加返回值,单入参就返回long型的rowId。多入参就定义返回值,数组型的rowId。TODO验证是需要定义还是自行追加。

Update
@Dao
interface UserDao {@Updatefun updateUsers(vararg users: User)
}

可以追加返回值,指示成功更新的行数。TODO验证是否会优先插入。

现在Insert和Update都只有三个OnConflictStrategy可选,REPLACE,IGNORE和ABORT。

Delete
@Dao
interface UserDao {@Deletefun deleteUsers(vararg users: User)
}

可以删除1个或者多个。会根据主键去删除,如果没有相同主键的行,就不会有任何改变。可以追加返回值,返回的是int的删除行数。

3.2 复杂方法(Query)

不要认为query就是查询了。@Query注解,可以自定义SQL语句。有个优点是编译就会报错来提示你。

简单查询
@Query("SELECT * FROM user")
fun loadAllUsers(): Array<User>

查询所有User对象。

返回表中多列的子集
  • 通过定义一个简单的类:
data class NameTuple(@ColumnInfo(name = "first_name") val firstName: String?,@ColumnInfo(name = "last_name") val lastName: String?
)
  • 定义DAO函数:
@Query("SELECT first_name, last_name FROM user")
fun loadFullName(): List<NameTuple>
简单参数传递

传参的目的为了过滤操作。例如,以下代码定义了一个返回超过特定年龄的所有用户的方法:

@Query("SELECT * FROM user WHERE age > :minAge")
fun loadAllUsersOlderThan(minAge: Int): Array<User>@Query("SELECT * FROM user WHERE age BETWEEN :minAge AND :maxAge")
fun loadAllUsersBetweenAges(minAge: Int, maxAge: Int): Array<User>@Query("SELECT * FROM user WHERE first_name LIKE :search " +"OR last_name LIKE :search")
fun findUserWithName(search: String): List<User>
将一组参数传递
@Query("SELECT * FROM user WHERE region IN (:regions)")
fun loadUsersFromRegions(regions: List<String>): List<User>
3.5 返回Cursor
@Dao
interface UserDao {@Query("SELECT * FROM user WHERE age > :minAge LIMIT 5")fun loadRawUsersOlderThan(minAge: Int): Cursor
}

不推荐,因为它无法保证行是否存在或行包含哪些值。

四、定义对象之间的关系

4.1 两张表之间的混合查询

在 Room 中,您可以通过两种方式定义和查询实体之间的关系:

  • 使用具有嵌入式对象的中间数据类。

  • 使用具有多重映射返回值类型的关系型查询方法。

中间数据类

在中间数据类方法中,您可以定义数据类,以便在 Room 实体之间建立关系。此数据类保存一个实体的实例与另一个实体的实例之间的配对(作为嵌入式对象)。然后,查询方法可以返回此数据类的实例,以供您的应用使用。

例如,您可以定义 UserBook 数据类来表示已借阅特定图书的图书馆用户,并定义一个查询方法用于从数据库中检索 UserBook 实例的列表:

@Dao
interface UserBookDao {@Query("SELECT user.name AS userName, book.name AS bookName " +"FROM user, book " +"WHERE user.id = book.user_id")fun loadUserAndBookNames(): LiveData<List<UserBook>>
}data class UserBook(val userName: String?, val bookName: String?)
返回Map(推荐)

room2.4支持如下操作:

@Query("SELECT * FROM user" +"JOIN book ON user.id = book.user_id"
)
fun loadUserAndBookNames(): Map<User, List<Book>>
4.2 创建嵌套对象(@Embeded)

有时,您可能希望在数据库逻辑中将某个实体或数据对象表示为一个紧密的整体,即使该对象包含多个字段也是如此。在这些情况下,您可以使用 @Embedded 注释表示要分解为表格中的子字段的对象。然后,您可以像查询其他各个列一样查询嵌套字段。

例如,您的 User 类可以包含一个 Address 类型的字段,它表示名为 streetcitystatepostCode 的字段的组合。若要在表中单独存储组合列,请在带有 @Embedded 注解的 User 类中添加 Address 字段,如以下代码段所示:

data class Address(val street: String?,val state: String?,val city: String?,@ColumnInfo(name = "post_code") val postCode: Int
)@Entity
data class User(@PrimaryKey val id: Int,val firstName: String?,@Embedded val address: Address?
)

然后,表示 User 对象的表将包含具有以下名称的列:idfirstNamestreetstatecitypost_code

七、更高级的用法

暂时不去学习,备查。查看官网。

2.5 表搜索支持
2.6 autoValue,java不可变值类
3.3 查询多张表

您的部分查询可能需要访问多个表格才能计算出结果。您可以在 SQL 查询中使用 JOIN 子句来引用多个表。

以下代码定义了一种方法将三个表进行联接,以便返回当前已出借给特定用户的图书:

@Query("SELECT * FROM book " +"INNER JOIN loan ON loan.book_id = book.id " +"INNER JOIN user ON user.id = loan.user_id " +"WHERE user.name LIKE :userName"
)
fun findBooksBorrowedByNameSync(userName: String): List<Book>
进阶

此外,您还可以定义简单对象以从多个联接表返回若干列的子集,如【返回表中多列的子集】部分所述。以下代码定义了一个 DAO,其中包含一个返回用户姓名和所借阅图书名称的方法:

interface UserBookDao {@Query("SELECT user.name AS userName, book.name AS bookName " +"FROM user, book " +"WHERE user.id = book.user_id")fun loadUserAndBookNames(): LiveData<List<UserBook>>// You can also define this class in a separate file.data class UserBook(val userName: String?, val bookName: String?)
}
进阶2-返回Map
//您可以直接从您的查询方法返回 `User` 和 `Book` 的映射,而不是返回保存有 `User` 和 `Book` 实例配对的自定义数据类的实例列表。
@Query("SELECT * FROM user" +"JOIN book ON user.id = book.user_id"
)
fun loadUserAndBookNames(): Map<User, List<Book>>//GROUP BY以便利用 SQL 的功能进行高级计算和过滤。
@Query("SELECT * FROM user" +"JOIN book ON user.id = book.user_id" +"GROUP BY user.name WHERE COUNT(book.id) >= 3"
)
fun loadUserAndBookNames(): Map<User, List<Book>>//如果您不需要映射整个对象,还可以通过在查询方法的 @MapInfo 注解中设置 keyColumn 和 valueColumn 属性,返回查询中特定列之间的映射:
@MapInfo(keyColumn = "userName", valueColumn = "bookName")
@Query("SELECT user.name AS username, book.name AS bookname FROM user" +"JOIN book ON user.id = book.user_id"
)
fun loadUserAndBookNames(): Map<String, List<String>>
3.4 Paging结合使用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/90194.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/90194.shtml
英文地址,请注明出处:http://en.pswp.cn/web/90194.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DOM编程全解析:操作、事件与存储实战指南

引言&#xff1a;DOM——JavaScript与网页交互的桥梁 DOM&#xff08;文档对象模型&#xff09; 是JavaScript操作HTML/XML文档的接口&#xff0c;它将网页文档抽象为一个树形结构&#xff0c;允许开发者通过API动态修改文档的内容、结构和样式。无论是实现动态交互&#xff0…

Ansible命令

Ansible命令 ansible 常用命令 /usr/bin/ansible   #Ansibe AD-Hoc 临时命令执行工具&#xff0c;常用于临时命令的执行 /usr/bin/ansible-doc    #Ansible 模块功能查看工具 /usr/bin/ansible-galaxy   #下载/上传优秀代码或Roles模块 的官网平台&#xff0c;基于网…

SY6974芯片添加enable充电控制节点

1. 需求描述项目背景&#xff1a;基于 Qualcomm MDM9x07 平台的 4G MIFI 产品&#xff0c;使用 Silergy 公司的 SY6974 充电 IC需求内容&#xff1a; 在环境 /sys/class/power_supply/sy6794/enable 下增加一个 sysfs 节点&#xff0c;用于控制是否允许充电&#xff1a;cat /sy…

趣玩-Ollama-Llm-Chatrbot

软件说明 这个软件本人是从零开始实现的聊天机器人。基于Ollama&#xff08;PythonApi &#xff09; Pyside&#xff0c;实现了聊天机器的基本功能&#xff0c;还有一些个性化的功能比如模型管理&#xff0c;敏感词过滤&#xff0c;个性化主题设置&#xff0c;头像设置等功能。…

在mac 上zsh 如何安装最新的 go 工具

文章目录方法一&#xff1a;使用 Homebrew&#xff08;推荐&#xff09;方法二&#xff1a;从官网下载安装包方法三&#xff1a;使用 g&#xff08;Go 版本管理器&#xff09;方法四&#xff1a;使用 gvm&#xff08;Go Version Manager&#xff09;验证安装和配置常用 Go 工具…

(十九)深入了解 AVFoundation-编辑:使用 AVMutableVideoComposition 实现视频加水印与图层合成(上)——理论篇

一、引言在短视频、Vlog、剪辑工具日益流行的今天&#xff0c;给视频添加 Logo、水印、时间戳或动态贴纸&#xff0c;已经成为非常常见的功能需求。这类效果看似简单&#xff0c;其实背后都涉及到“图层合成”的处理&#xff1a;如何将一个静态或动态的图层&#xff08;如文字、…

Android NDK与JNI深度解析

核心概念定义&#xff1a;NDK (Native Development Kit): 是什么&#xff1a; 一套由 Google 提供的工具集合。目的&#xff1a; 允许 Android 开发者使用 C 和 C 等原生&#xff08;Native&#xff09;语言来实现应用程序的部分功能。包含内容&#xff1a; 交叉编译器&#xf…

Golang各版本特性

1. Go各版本特性 | FeelingLife 2. https://chatgpt.com/share/68808f58-ae5c-800a-8153-5358098f301b 3.https://tonybai.com/2024/11/14/go-map-use-swiss-table/

HTML 转 Word API 接口

HTML 转 Word API 接口 支持网页转 Word&#xff0c;高效转换为 Word&#xff0c;提供永久链接。 1. 产品功能 超高性能转换效率&#xff1b;支持将传递的 HTML 转换为 Word&#xff0c;支持 HTML 中的 CSS 格式在 Word 文档中的呈现&#xff1b;支持传递网站的 URL&#xff…

Lucid Search: 极简、隐私友好的问答式搜索引擎技术解析

Lucid Search: 极简、隐私友好的问答式搜索引擎技术解析 产品定位与价值主张 Lucid Search 是一款革命性的问答式搜索引擎&#xff0c;其核心价值在于&#xff1a; 极简体验&#xff1a;无账户、无广告、前端完全静态隐私保护&#xff1a;不写入 Cookie、不记录 IP、无追踪即…

卷积神经网络:模型评估标准

一、分类模型评价指标在模型评估中&#xff0c;有多个标准用于衡量模型的性能&#xff0c;这些标准包括准确率&#xff08;Accuracy&#xff09;、精确率&#xff08;Precision&#xff09;、召回率&#xff08;Recall&#xff09;、F1 分数&#xff08;F1-Score&#xff09;等…

【前端工程化】前端开发中想做好发布管理可以从哪些方面着手?

在企业级后台系统中&#xff0c;发布管理是整个开发流程的最终环节&#xff0c;也是最为关键的一环。它不仅涉及代码构建完成后的部署操作&#xff0c;还包括版本控制、灰度发布、回滚机制等保障系统稳定性的措施。 本文主要围绕发布流程设计、版本控制、部署方式、灰度策略和回…

替分布式=成本下降50% !

在数字化转型的浪潮中&#xff0c;数据库作为医疗信息系统的“心脏”&#xff0c;其稳定性与效率直接关乎医疗服务的质量。2024年10月30日&#xff0c;绵阳市第三人民医院集成平台的CDR数据库成功从分布式数据库Citus切换为国产集中式数据库KingbaseES&#xff0c;并稳定运行至…

【Linux系统编程】基础指令

基础指令1. adduser指令&&passwd指令2. userdel指令3. pwd指令4. ls指令5. cd指令6. tree指令7. touch指令8. mkdir指令9. rmdir指令&&rm指令10. man指令11. cp指令12. mv指令13. cat指令14. more指令15. less指令16. head指令17. tail指令18. date指令19. cal…

区块链之以太坊Hardhat开发框架——部署在windows为例

Hardhat 提供了一个灵活且易于使用的开发环境&#xff0c;可以轻松地编写、测试和部署智能合约。Hardhat还内置了Hardhat 网络&#xff08;Hardhat Node&#xff09;&#xff0c;它是为开发而设计的本地以太坊网络。 下面是hardhat的官方文档 https://hardhat.org/hardhat-ru…

Ubuntu 1804 编译ffmpeg qsv MediaSDK libva 遇到的问题记录

之前都是 用的xeon服务器的cpu 不支持intel QSV 硬件加速 最近把自己的 14年买的pc机装上了ubuntu 1804 然后准备开启ffmpeg qsv 硬件加速功能 CPU i3-4170 内存DDR3 16G 硬盘机械盘500G 主板ASUS B85M-G首先安装vainfo工具apt install vainfo装完提示如下出错了 网上说是…

Elasticsearch(ES)介绍和安装

目录 一、Elasticsearch(ES)介绍 1.为什么需要单独的搜索服务 2.全文检索 3.Elasticsearch简介 1.Elasticsearch的特点 2.应用场景 3.ElasticSearch数据的存储和搜索原理 二、Elasticsearch(ES)安装 1、拉取镜像 2、创建目录并给目录赋权 3、创建并编辑配置文件 4、…

html结构解析

<!DOCTYPE html>&#xff1a;声明为 HTML5 文档 <html lang"zh-CN">&#xff1a;根元素&#xff0c;指定页面语言为中文 <meta charset"UTF-8">&#xff1a;设置字符编码&#xff0c;确保中文正常显示 <meta name"viewport"…

面试150 最大子数组和

思路 贪心法&#xff1a;设定最小标志result为float(‘-inf’),遍历一次数组元素进行求和&#xff0c;如果当前元素大于result&#xff0c;则更新result的值&#xff0c;如果sum小于0&#xff0c;则重新置0进行计算&#xff0c;最后返回result class Solution:def maxSubArray(…

MyBatis动态SQL实战:告别硬编码,拥抱智能SQL生成

MyBatis动态SQL实战&#xff1a;告别硬编码&#xff0c;拥抱智能SQL生成在电商平台的用户管理模块中&#xff0c;需要面对多种不同的用户查询组合条件。当使用传统的硬编码SQL方式时&#xff0c;代码膨胀到了2000多行&#xff0c;维护成本极高。而引入MyBatis动态SQL后&#xf…