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
相关产品推荐
相关产品推荐

