database - Android房间数据库插入/更新序列
问题描述
我有一个带有 Room 数据库的应用程序,包括 DAO 和存储库。事件顺序如下:
- 插入新行。
- 将行发送到服务器
- 更新该行以指示该行已被发送。
问题是新行的 ID 在我发送到服务器之前或更新时并不总是可用的。因此,DAO 更新方法不起作用,因为它没有正确的 ID。
在我继续之前让插入返回 ID 是否有技巧?我知道这是在规避异步进程的好处,但在这种情况下可能是必要的。我希望其他人可能已经解决了这个问题。
解决方案
问题是在我发送到服务器之前,新行的 ID 并不总是可用
对于 Room 中的表,如果通过便利 @Insert 插入行,则始终有一个唯一标识可用插入行的值(如果使用则不同@Query("INSERT INTO .....")
)
- 请注意,如果由于捕获/处理冲突而未插入该行,则返回的值将为 -1。
在我继续之前让插入返回 ID 是否有技巧?
不是真正的技巧,至少如果ID是整数类型,更多的是预期/预期的用法。只需让insert Dao 返回 Long(如果 java 则返回 long)
例如(Java)
@Insert
long insert(TheEntity theEntity);
或(科特林)
@Insert
fun insert(theEntity: TheEntity): Long
返回的 Long/long 将是rowid列的值或其别名。
rowid是所有表都有的列(除了那些用 WITHOUT ROWID 定义的表,Room 不允许),尽管它是一个隐藏列。如果您编写使用 @PrimaryKey 注释的整数类型,则该列将是rowid的别名。
注意整数类型,你可以有
- 长长的,
- 整数,整数整数,
- 短,短,
- 字节,字节,
- 甚至,尽管它很无用,布尔值,布尔值。
然而,Long,long 是最适合id列的值,因为 SQLite 可以存储一个 64 位有符号整数,它等于 Long/long。因此,为什么插入只能返回 Long/long。
不使用 Long/long SQLite 的优势很小(如果有的话)会将值存储在从 1 字节到 8 字节的尽可能小的空间中。因此,值 1 无论是 byte/short/int/long 在存储在数据库中时都会占用一个字节。
例如对于 Kotlin 代码
fun insert(toDoData: ToDoData): Int
,你会得到error: Not sure how to handle insert method's return type. public abstract int insert(@org.jetbrains.annotations.NotNull()
非整数 ID 类型/复合主键
其他列类型 String、Byte[]、Double、Float 等,或复合主键,不会是 rowid 列的别名。要从这些其他类型中获取主键,您可以使用返回的 rowid,因为它对行是唯一的,然后获取主键,例如 (for @PrimaryKey val id: String
)
@Query("SELECT id FROM todo_table WHERE rowid=:rowid" )
fun getPrimaryKeyByRowid(rowid: Long): String`
当然,您可以绕过获取 PrimayKey 值并传递,然后使用rowid值来确定要更新的行,但不使用@Update
便捷方法/函数,而是@Query
使用UPDATE .... WHERE rowid=:passRowid
.
推荐阅读
- python - 将日期写入 CSVFile python 的顶部
- linux - Docker容器中的Android Studio模拟器问题
- google-photos - 从谷歌照片 api 下载的视频质量不是最好的
- javascript - Flutter 对 Cloud 函数的调用正在解决 DEADLINE_EXCEEDED 云函数异常
- sql-server - 结合聚集列存储索引和非聚集列存储索引的好处?
- django - 使用外键获取 Django 模型中的根节点
- amazon-web-services - 无法使用 Go SDK 下载大于 100MB 的 S3 对象
- python-3.x - urllib.request 在行为上与 curl 或 httpx 有何不同?在向 Google Container Registry 的请求中获取 401
- r - ggplot y 轴应该是实值连续的,而是二进制 1-0
- c - 使用计时器多次 fork()