You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Room DAO同时使用@Insert与@Upsert编译失败问题排查

Room DAO编译错误:找不到upsert方法的原因与解决办法

问题代码

package com.example.secondcompose.dao

import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Upsert
import com.example.secondcompose.data.Phone
import kotlinx.coroutines.flow.Flow

@Dao
interface PhoneDao {
    @Insert(onConflict = OnConflictStrategy.NONE)
    suspend fun insertIfMissing(phone: Phone)

    @Upsert
    suspend fun upsert(phone: Phone)

    @Delete
    suspend fun delete(phone: Phone)

    @Query("DELETE FROM phone")
    suspend fun nuke()

    @Query("SELECT * FROM phone WHERE id = :id")
    fun find(id: Long): Flow<Phone?>

    @Query("SELECT * FROM phone ORDER BY manufacturer ASC")
    fun getPhonesOrderedByManufacturer(): Flow<List<Phone>>
}

编译报错信息

C:\Users\szmar\AndroidStudioProjects\SecondCompose\app\build\generated\ksp\debug\java\com\example\secondcompose\dao\PhoneDao_Impl.java:160: error: cannot find symbol
          __insertionAdapterOfPhone.upsert(phone);
                                   ^
  symbol:   method upsert(Phone)
  location: variable __insertionAdapterOfPhone of type EntityInsertionAdapter<Phone>

原因分析

Room生成DAO实现类时,若同时存在@Insert和@Upsert注解的方法,会错误复用同一个EntityInsertionAdapter实例处理两种操作。但EntityInsertionAdapter本身并不提供upsert方法——该操作需要的是UpsertionAdapter,这是Room旧版本代码生成逻辑的bug。

解决方案

方案1:升级Room到最新稳定版

Room 2.5.0及以上版本已修复此代码生成问题。在Module级build.gradle文件中更新依赖版本:

dependencies {
    def room_version = "2.6.1" // 替换为最新稳定版
    implementation "androidx.room:room-runtime:$room_version"
    ksp "androidx.room:room-compiler:$room_version"
    implementation "androidx.room:room-ktx:$room_version"
}

方案2:替换@Upsert为@Insert(REPLACE)

若暂时无法升级版本,可将@Upsert替换为@Insert(onConflict = OnConflictStrategy.REPLACE),二者功能等价(不存在则插入,存在则替换):

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun upsert(phone: Phone)

方案3:自定义Upsert的SQL查询

如果需要精细控制更新字段(而非替换整个实体),可以用@Query手写Upsert逻辑:

@Query("""
    INSERT INTO phone (id, manufacturer, model)
    VALUES (:phone.id, :phone.manufacturer, :phone.model)
    ON CONFLICT(id) DO UPDATE SET
        manufacturer = :phone.manufacturer,
        model = :phone.model
""")
suspend fun upsert(phone: Phone)

(注意:需根据Phone实体的实际字段调整SQL中的列名和赋值内容)


内容的提问来源于stack exchange,提问作者Szymon Marczak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 14:45:05