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

Requery自动数据库迁移报错:无法添加非空列且默认值为NULL

解决Android数据库迁移新增非空列报错问题

这个报错的核心原因很明确:你新增了一个NOT NULL的整数字段,但没有给这个字段指定数据库层面的默认值。当数据库自动迁移时,现有数据行没有这个字段的值,数据库无法用NULL填充(因为字段不允许为空),所以抛出了这个错误。下面针对Android常用的ORM框架给出具体解决方法:

方法1:通过实体类注解指定数据库默认值

如果用的是Room这类支持注解配置的ORM,直接给新增字段加上@ColumnInfo注解,明确指定defaultValue:

public abstract class AbstractFooEntity {
    // 其他已有字段...
    
    // 新增的非空整数字段,指定数据库默认值为0
    @ColumnInfo(name = "new_int_field", defaultValue = "0")
    private int newIntField;
}

⚠️ 注意:defaultValue的值必须是字符串形式,因为框架会直接把这个值拼接到SQL语句中。比如这里写"0"而不是0,生成的SQL会是ADD COLUMN new_int_field INTEGER NOT NULL DEFAULT 0,数据库就能正确给现有行填充默认值了。

同时建议给Java字段也设置初始值(比如private int newIntField = 0;),避免新创建实体对象时出现空值问题——这一步是代码层面的健壮性优化,不影响数据库迁移,但能减少后续潜在问题。

方法2:手动编写迁移脚本(当自动迁移不生效时)

如果框架自动迁移功能无法识别默认值配置,或者需要更灵活的迁移逻辑,就需要手动编写Migration类,直接执行SQL语句:

// 假设旧版本是1,新版本是2
static final Migration MIGRATION_1_2 = new Migration(1, 2) {
    @Override
    public void migrate(@NonNull SupportSQLiteDatabase database) {
        // 直接执行ALTER TABLE语句,明确指定默认值
        database.execSQL("ALTER TABLE AbstractFooEntity ADD COLUMN new_int_field INTEGER NOT NULL DEFAULT 0");
    }
};

然后在初始化DatabaseSource的时候,把这个迁移脚本添加进去:

// 注意DB_VERSION要改成新的版本号
DatabaseSource databaseSource = new DatabaseSource(context, Models.DEFAULT, NEW_DB_VERSION);
databaseSource.addMigrations(MIGRATION_1_2);

关键注意事项

  • 不要只依赖Java字段的默认值:Java的默认值(比如int类型默认0)只对新创建的实体对象生效,数据库迁移时操作的是现有数据行,必须在SQL层面指定默认值。
  • 确认数据库版本号正确:确保DB_VERSION已经升级到比旧版本更高的数值,这样框架才会触发迁移逻辑。

内容的提问来源于stack exchange,提问作者jakub.g

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:11:50