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

Android Room @Upsert注解触发SQLite唯一约束异常排查

Android Room @Upsert触发唯一约束异常的原因及解决方法

问题根源

Room的@Upsert默认仅以实体类的主键作为冲突判断依据。你的CoinStatus实体中,主键是自增的primaryKey,而唯一约束定义在coin_query_id字段上。当调用updateFavorites时,传入的CoinStatus对象的primaryKey通常是默认值(比如0),Room会判定这是新实体并执行插入操作,而此时coin_query_id已存在于数据库中,直接触发唯一约束冲突异常。

解决方案

方案一:将coin_query_id设为主键(推荐,逻辑更清晰)

既然coin_query_id本身是唯一的,直接把它设为主键,去掉多余的自增主键。这样@Upsert会自动基于这个唯一主键判断冲突:

@Entity(tableName = "coin_status")
public class CoinStatus {
    @PrimaryKey
    @ColumnInfo(name = "coin_query_id")
    private String coinQueryId;

    @ColumnInfo(name = "is_favorite")
    private boolean isFavorite;

    public CoinStatus(String coinQueryId, boolean isFavorite) {
        this.coinQueryId = coinQueryId;
        this.isFavorite = isFavorite;
    }

    // 省略getter和setter
}

修改后,@Upsert会正常工作:存在对应coin_query_id的记录时更新,不存在时插入。

方案二:指定@Upsert的冲突判断列(Room 2.4.0+可用)

如果必须保留自增主键,可在@Upsert注解中指定conflictColumns参数,明确以coin_query_id作为冲突判断依据:

@Dao
public interface CoinStatusDao {
    @Upsert(conflictColumns = {"coin_query_id"})
    Single<List<Long>> updateFavorites(List<CoinStatus> favoriteCoins);
}

注意:该特性要求Room版本≥2.4.0,若你的Room版本较低,此方案不可用。

方案三:自定义SQL实现Upsert(兼容所有Room版本)

如果上述方案都不适用,可直接用INSERT OR REPLACE的SQL语句手动实现Upsert逻辑:

@Dao
public interface CoinStatusDao {
    // 单条数据Upsert
    @Query("INSERT OR REPLACE INTO coin_status (coin_query_id, is_favorite) VALUES (:coinQueryId, :isFavorite)")
    int upsertSingleFavorite(String coinQueryId, boolean isFavorite);

    // 批量Upsert(需配合事务)
    @Transaction
    default List<Integer> upsertFavorites(List<CoinStatus> favoriteCoins) {
        List<Integer> resultList = new ArrayList<>();
        for (CoinStatus status : favoriteCoins) {
            int affectedRows = upsertSingleFavorite(status.getCoinQueryId(), status.isFavorite());
            resultList.add(affectedRows);
        }
        return resultList;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 11:55:39