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

如何解决Room中“预打包数据库架构无效”问题?

数据库架构与Room Entity类不匹配问题解决

错误信息

Expected:
  TableInfo{name='activities', columns={activityId=Column{name='activityId', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1, defaultValue='undefined'}, emojiId=Column{name='emojiId', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}, visibility=Column{name='visibility', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='undefined'}, act_label=Column{name='act_label', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='undefined'}, latitude=Column{name='latitude', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='undefined'}, ownerId=Column{name='ownerId', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}, title=Column{name='title', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='undefined'}, act_date=Column{name='act_date', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='undefined'}, act_location=Column{name='act_location', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='undefined'}, desc=Column{name='desc', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}, longitude=Column{name='longitude', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='undefined'}}, foreignKeys=[ForeignKey{referenceTable='user', onDelete='CASCADE +', onUpdate='NO ACTION', columnNames=[ownerId], referenceColumnNames=[id]}], indices=[]}
Found:
  TableInfo{name='activities', columns={activityId=Column{name='acti vityId', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1, defaultValue='undefined'}, ownerId=Column{name='ownerId', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}, title=Column{name='title', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='undefined'}, desc=Column{name='desc', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}, visibility=Column{name='visibility', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}, latitude=Column{name='latitude', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}, longitude=Column{name='longitude', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}, emojiId=Column{name='emojiId', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}}, foreignKeys=[ForeignKey{referenceTable='user', onDelete='NO ACTION +', onUpdate='NO ACTION', columnNames=[ownerId], referenceColumnNames=[id]}], indices=[]}
    at androidx.room.RoomOpenHelper.onCreate(RoomOpenHelper.kt:73)

当前Entity类代码

@Entity(
    tableName = "activities",
    foreignKeys = [
        ForeignKey(
            entity = Users::class, // Assuming your user entity class is named User
            parentColumns = ["id"],
            childColumns = ["ownerId"],
            onDelete = ForeignKey.CASCADE, // Correct onDelete action
        )
    ]
)
data class Activities(
    @PrimaryKey(autoGenerate = true)val activityId: Int,
    @ColumnInfo(name = "ownerId") val ownerId: Int?,
    @ColumnInfo(name = "title") @NotNull val title: String,
    @ColumnInfo(name = "desc") val desc: String?,
    @ColumnInfo(name = "visibility") val visibility: Int,
    @ColumnInfo(name = "latitude")  val latitude: Int,
    @ColumnInfo(name = "longitude")  val longitude: Int,
    @ColumnInfo(name = "emojiId") val emojiId: Int?,
    @Ignore val actLabel: String, // New column
    @Ignore val actDate: Int, // New column
    @Ignore @NotNull val actLocation: String, // New column
) : Serializable

问题分析

对比预期与实际表结构,核心差异点如下:

  • 缺失核心列:act_label、act_date、act_location在预期结构中存在,但当前Entity给这三个字段加了@Ignore注解,导致Room未生成对应数据库列。
  • 非空性不匹配:visibility、latitude、longitude预期为非空,但Entity未添加@NotNull注解,数据库生成了可空列;主键activityId预期非空,但未设置默认值,Room无法确保其非空性。
  • 外键行为不符:预期外键onDelete=CASCADE,但实际数据库中是NO ACTION,大概率是Entity修改后未同步数据库版本。
  • 主键列名异常:实际表中主键列名为acti vityId(含空格),需确认Entity中activityId拼写无空格(大概率是错误信息排版问题)。

修正后的Entity类代码

@Entity(
    tableName = "activities",
    foreignKeys = [
        ForeignKey(
            entity = Users::class,
            parentColumns = ["id"],
            childColumns = ["ownerId"],
            onDelete = ForeignKey.CASCADE
        )
    ]
)
data class Activities(
    @PrimaryKey(autoGenerate = true) val activityId: Int = 0, // 设置默认值确保非空
    @ColumnInfo(name = "ownerId") val ownerId: Int?,
    @ColumnInfo(name = "title") @NotNull val title: String,
    @ColumnInfo(name = "desc") val desc: String?,
    @ColumnInfo(name = "visibility") @NotNull val visibility: Int, // 添加@NotNull
    @ColumnInfo(name = "latitude") @NotNull val latitude: Int, // 添加@NotNull
    @ColumnInfo(name = "longitude") @NotNull val longitude: Int, // 添加@NotNull
    @ColumnInfo(name = "emojiId") val emojiId: Int?,
    @ColumnInfo(name = "act_label") @NotNull val actLabel: String, // 移除@Ignore并指定列名
    @ColumnInfo(name = "act_date") @NotNull val actDate: Int, // 移除@Ignore并指定列名
    @ColumnInfo(name = "act_location") @NotNull val actLocation: String // 移除@Ignore并指定列名
) : Serializable

额外注意事项

  1. 更新数据库版本:修改Entity后,需提升@Database注解中的version值,添加迁移规则;开发阶段可临时使用fallbackToDestructiveMigration()重建数据库(生产环境禁用)。
  2. 列名映射校验:确保@ColumnInfo(name = "...")与数据库列名完全一致,比如act_label对应Entity中的actLabel。
  3. 主键规范:autoGenerate=true的主键设置默认值0,Room会在插入时自动生成正确主键值,同时保证字段非空。

内容的提问来源于stack exchange,提问作者Mahmut Emin Yavuz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 02:26:04