虽然对于rowId,@Insert返回Long或其集合,而对于受影响的行数,@Delete@Update返回Int,那么@Upsert可以返回什么?

参考:https://developer.android.com/training/data-storage/room/accessing-data

推荐答案

使用@Upsert批注调用的函数/方法可以返回

  1. 无/无效,或
  2. 长/长,或
  3. 长/长的数组(如果可能有多个插入).
  • the returned value should be the rowid of the inserted or replaced row.
    • Rowid是一个通常隐藏的列,所有典型的Room表都有.
    • if the PRIMARY KEY is a single field/member 和 that field/member is an integer type (Long, Int, int, long even Boolean 和 so on) then the PRIMARY KEY will be an alias of the rowid 和 thus the PRIMARY KEY of the inserted row
    • if the PRIMARY KEY consists of multiple columns or is not a single integer type column then the rowid still exists 和 can be used
  • it should be noted that Room does not use the SQLite UPSERT (at least currently) but uses an an SQLite INSERT OR REPLACE (和 hence returns the same values that an @Insert does).

通过编码和编译就可以很容易地确定

例如,使用

@Upsert
fun upsert(parent: PartCargo): Int

顶级编译失败,Not sure how to h和le upsert method's return type.

同时,

@Upsert
fun upsert(parent: PartCargo): Long

@Upsert
fun upsert(parent: PartCargo)

编译成功.

然而,

@Upsert
fun upsert(parent: PartCargo): LongArray

失败,错误为Upsert method accepts a single parameter but the return type is a collection of elements.

同时,

@Upsert
fun upsert(parents: List<PartCargo>): LongArray

编译成功.

  • all the above are Kotlin, but Java is similar (hence void 和 long in the initial part of the answer).

Additional

can you add a reference about Room's implementation of Upsert that behind the scene only do insert 和 replace before I accept this answer?

如果有参考文献,则不需要.实际上在"幕后"做了什么很容易确定.

The "behind the scenes", is the annotation processer generating java code. This java generated java code forms part of the package 和 is what is actually used at runtime.

The 2 core/primary annotations are the @Database@Dao annotations. These determine the resultant classes that contain the respective generated java. The classes will be the name of the class/interface being processed suffixed with _Impl.

生成的Java放在文件夹的子文件夹中,通过Android Studio中的Android View显示为Java(生成的).通常会有两个同名的子文件夹.其中一个将被视为包含已生成的各个类.

例如,上述代码摘录摘自以下内容:

enter image description here

The extracts were from the @Dao annotated interface interface DetailsDAO .... 和 hence the DetailsDAO_Impl class that has been generated.

搜索Upsert找到:-

enter image description here

  • 注意不要编辑文件的警告
    • 实际上,有时可以忽略,例如添加断点进行调试

It is then just a matter of ascertaining the respective code utilised 和 the SQL invoked. For the above the eventual respective code is:-

this.__insertionAdapterOfPartCargo = new EntityInsertionAdapter<PartCargo>(__db) {
      @Override
      @NonNull
      protected String createQuery() {
        return "INSERT OR REPLACE INTO `parts` (`tId`,`detailsTId`,`id`,`name`) VALUES (nullif(?, 0),?,?,?)";
      }

Android相关问答推荐

当我的Log.i()不在主线程中时,如何在我的logcat中显示它?

编写视觉转型

无法使用MenuItemColors.Copy()

从单元测试访问RES/RAW文件

DocumentFile.canWrite()、DocumentFile.Existes()-使用本地内置手机存储(而不是云)时性能较差(占用太多CPU时间)

为什么柱子的高度不都一样?

Android布局渲染问题

是否可以附加事件处理程序,如onClick,拖动到Canvas Composable中绘制的内容,或使用drawBehind修饰符?

需要 java 17 而不是 java 11:Android CI-CD GitHub Actions

在 Bash 脚本中使用 XMLLINT 解析 XML 单元测试文件,并将其放入数组中以表示成功和失败

为什么我的 APK 中包含来自旧版 Android 支持库的类?

appcompat 依赖从何而来?

列表更改时,RecyclerView 中的列表不会更新

延时kotlin中时分秒的使用方法

react 从输入中找到路径'lib/arm64-v8a/libfbjni.so'的本机2个文件

状态值更改时屏幕未重新组合 - Jetpack Compose

为什么我在 Jetpack Compose 中被警告可选修饰符参数应该具有默认值修饰符?

构成material 3 中的分隔符

Android:在模块 jetified-play-services-measurement 和 jetified-play-services-measurement-impl 中发现重复类

为什么在try 实例化 Mediaplayer 时会出现 NullPointerException?安卓Kotlin