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

Android SQLite迁移后新插入记录的新增字段为null

问题描述

Android SQLite数据库完成迁移后,新增字段始终存储为null。操作流程为在实体类中新增对应字段,编写迁移方法完成新列添加与存量数据赋值:通过Database Inspector可确认新列已成功创建,存量记录的该列值已正常填充,但新增记录时,除该新增字段外其余字段均可正常存储。

实体类代码

@DatabaseTable(tableName = "organizer_item")
public class OrganizerItem {

    public static final String TABLE_NAME = "organizer_item";
    public static final String COLUMN_ID = "id";
    public static final String COLUMN_DATE = "date";
    public static final String COLUMN_NOTIFICATION_DATE = "notification_date";
    public static final String COLUMN_TEXT = "text";

    @DatabaseField(generatedId = true, columnName = COLUMN_ID)
    private int id;

    @DatabaseField(columnName = COLUMN_DATE)
    private long dateTime;

    @DatabaseField(columnName = COLUMN_TEXT)
    private String text;

    @DatabaseField(columnName = COLUMN_NOTIFICATION_DATE)
    private long notificationDateTime;

    public OrganizerItem(){}

    public OrganizerItem(long dateTime,long notificationDateTime, String text) {
        this.dateTime = dateTime;
        this.text = text;
        this.notificationDateTime = notificationDateTime;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public long getDateTime() {
        return dateTime;
    }

    public void setDateTime(long dateTime) {
        this.dateTime = dateTime;
    }

    public long getNotificationDateTime() {
        return notificationDateTime;
    }

    public void setNotificationDateTime(long notificationDateTime) {
        this.notificationDateTime = notificationDateTime;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }
}

迁移逻辑代码

private void upgrade(SQLiteDatabase db) {
    String addNotificationDateTimeQuery = ("ALTER TABLE " + OrganizerItem.TABLE_NAME + " ADD COLUMN "
            + OrganizerItem.COLUMN_NOTIFICATION_DATE + " INTEGER");
    db.execSQL(addNotificationDateTimeQuery);
    long fiveMinAsMiliseconds = 5 * 60 * 1000;
    String initAddNotificationDateTimeQuery = ("UPDATE " + OrganizerItem.TABLE_NAME + " SET "
            + OrganizerItem.COLUMN_NOTIFICATION_DATE + " =  " + OrganizerItem.COLUMN_DATE + " - " + fiveMinAsMiliseconds);
    db.execSQL(initAddNotificationDateTimeQuery);
}

现象说明

  • 存量数据迁移后赋值正常,新列创建成功
  • 数据插入使用RuntimeExceptionDao<OrganizerItem, Integer>实例,写入操作调用organizerItemDao.update(organizerItem)
  • 写入前日志确认对象所有字段均已赋值:
OrganizerItem{id=0, dateTime=1654717800000, text='New Stackoverflow Test', notificationDateTime=1654717500000}
  • 新插入的记录中,仅notificationDateTime字段值为null,其余字段存储正常

问题原因与解决方案

核心原因

你使用的ORMLite框架如果开启了编译期生成表配置(ormlite_config.txt,用于替代运行时反射提升性能),新增实体字段后没有重新编译生成最新的配置文件,会导致ORMLite生成INSERT/UPDATE语句时,不会包含新增的notification_date字段。
由于你执行ALTER TABLE加列时没有给字段设置默认值,写入SQL不带该字段时,SQLite会自动给该字段赋值NULL,就会出现你看到的现象。迁移逻辑是直接执行原生SQL,不受ORMLite配置影响,所以存量数据赋值正常。

修复步骤

  1. 在Android Studio中执行Build > Clean Project,再执行Rebuild Project,让注解处理器重新生成包含新字段的表配置文件,重新运行应用即可解决新字段写入为null的问题。
  2. 修正新数据写入的方法调用:id为0的对象是未持久化的新对象,update()方法是用于更新已存在的记录(会按照id匹配行),插入新记录需要调用organizerItemDao.create(organizerItem),如果需要同时兼容新增和更新场景,使用createOrUpdate()方法。

内容的提问来源于stack exchange,提问作者Tomasz Stępnik

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 07:12:52