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

Android Room仅在Lollipop5.1(SDK22)出现主键位置重复的无效架构问题

问题:Room在Android 5.1(SDK22)下联合主键Schema验证崩溃

定义的Room Entity类

@Entity(tableName = "game_regions",
        primaryKeys = {"_game", "_region_area"},
        foreignKeys = {
                @ForeignKey(
                        entity = GameEntity.class,
                        parentColumns = "_id",
                        childColumns = "_game"
                ),
                @ForeignKey(
                        entity = RegionAreaEntity.class,
                        parentColumns = "_id",
                        childColumns = "_region_area"
                )})
public class GameRegionsEntity {

    @NonNull
    @ColumnInfo(name = "_game")
    private String game;

    @NonNull
    @ColumnInfo(name = "_region_area")
    private String regionArea;

    public GameRegionsEntity(@NonNull String game, @NonNull String regionArea) {
        this.game = game;
        this.regionArea = regionArea;
    }

    @NonNull
    public String getGame() {
        return game;
    }

    public void setGame(@NonNull String game) {
        this.game = game;
    }

    @NonNull
    public String getRegionArea() {
        return regionArea;
    }

    public void setRegionArea(@NonNull String regionArea) {
        this.regionArea = regionArea;
    }
}

对应的SQL建表语句

CREATE TABLE "game_regions" (
    "_game" TEXT NOT NULL,
    "_region_area"  TEXT NOT NULL,
    PRIMARY KEY("_game","_region_area"),
    FOREIGN KEY("_region_area") REFERENCES "region_areas"("_id"),
    UNIQUE("_game","_region_area"),
    FOREIGN KEY("_game") REFERENCES "games"("_id")
);

异常信息

java.lang.IllegalStateException: Pre-packaged database has an invalid schema: game_regions(GameRegionsEntity).
     Expected:
    TableInfo{name='game_regions', columns={_region_area=Column{name='_region_area', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=2, defaultValue='undefined'}, _game=Column{name='_game', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=1, defaultValue='undefined'}}, foreignKeys=[ForeignKey{referenceTable='games', onDelete='NO ACTION +', onUpdate='NO ACTION', columnNames=[_game], referenceColumnNames=[_id]}, ForeignKey{referenceTable='region_areas', onDelete='NO ACTION +', onUpdate='NO ACTION', columnNames=[_region_area], referenceColumnNames=[_id]}], indices=[]}
     Found:
    TableInfo{name='game_regions', columns={_game=Column{name='_game', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=1, defaultValue='undefined'}, _region_area=Column{name='_region_area', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=1, defaultValue='undefined'}}, foreignKeys=[ForeignKey{referenceTable='region_areas', onDelete='NO ACTION +', onUpdate='NO ACTION', columnNames=[_region_area], referenceColumnNames=[_id]}, ForeignKey{referenceTable='games', onDelete='NO ACTION +', onUpdate='NO ACTION', columnNames=[_game], referenceColumnNames=[_id]}], indices=null}

问题分析

对比预期与实际的TableInfo,唯一差异是:预期中两个联合主键的primaryKeyPosition分别为1和2,而Android 5.1设备上实际返回的primaryKeyPosition均为1。该问题仅在SDK22出现,原因是Android 5.1搭载的SQLite版本(3.8.10)较低,Room在解析该版本SQLite的系统表时,无法正确识别联合主键的顺序,导致Schema验证失败。

解决方案

方案1:禁用该表的Schema验证

在Room的@Database注解中,将game_regions表加入excludeFromValidation列表,跳过该表的Schema校验:

@Database(
    entities = {GameRegionsEntity.class, GameEntity.class, RegionAreaEntity.class},
    version = 1,
    excludeFromValidation = {"game_regions"}
)
public abstract class AppDatabase extends RoomDatabase {
    // ... DAO定义
}

方案2:升级Room版本

检查并升级Room到较新的稳定版本(如2.4.0及以上),部分低版本Room存在的旧SQLite兼容性问题已被修复。

方案3:改用Room Migration生成表

避免使用预打包数据库,改用Room的Migration机制在应用启动时创建表。Room会根据Entity定义自动生成符合各版本SQLite要求的建表语句,确保主键顺序被正确识别。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 02:40:29