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

Android Room中如何为实体字段配置唯一约束?

问题原因

你配置的联合唯一索引失效,核心问题是把自增主键id放进了唯一索引字段列表里:

  • id字段设置了autoGenerate = true,每次插入新数据都会自动生成全局不重复的值
  • 联合唯一索引的判定规则是所有索引字段的值完全一致,才会判定为重复、拦截插入
  • 只要每条数据的id不一样,哪怕audio_id重复,(id, audio_id)的组合也永远不会重复,约束自然完全不生效
正确实现方式

根据实际业务需求选对应方案即可:

方案1:要求audio_id全局唯一

如果业务规则是整张表里不允许出现重复的audio_id,直接给audio_id单独配置唯一索引即可,修改@Entity注解配置:

@Entity(
    tableName = "playlist_members",
    indices = [Index(value = ["audio_id"], unique = true)]
)
data class Members(
    @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "id") val id: Int?,
    var title: String,
    var artist: String,
    var album: String,
    @ColumnInfo(name = "audio_id") val audioId: Int,
    val albumId: String
)

也可以直接在audioId字段上加@Unique注解,效果和上面的单字段唯一索引完全一致:

@Entity(tableName = "playlist_members")
data class Members(
    @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "id") val id: Int?,
    var title: String,
    var artist: String,
    var album: String,
    @ColumnInfo(name = "audio_id") @Unique val audioId: Int,
    val albumId: String
)

方案2:要求指定组合下audio_id唯一

如果业务规则是「同一个维度下audio_id不允许重复,不同维度可以重复」(比如同一个歌单下不能重复添加同一首歌、不同歌单可以加同一首),就把对应的业务维度字段和audio_id配成联合唯一索引,注意不要把自增主键id放进去。举个例子,如果表中有playlistId字段标记所属歌单,联合唯一索引写法如下:

@Entity(
    tableName = "playlist_members",
    indices = [Index(value = ["playlist_id", "audio_id"], unique = true)]
)
注意事项

如果应用已经在设备上创建过这个数据库表,修改索引配置后不会自动生效:

  • 调试阶段可以直接卸载应用重装,让Room重新创建表结构
  • 正式环境必须升级数据库版本,编写对应的Migration逻辑执行SQL创建新的唯一索引,否则会出现数据库版本不匹配的崩溃

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 06:51:22