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配置影响,所以存量数据赋值正常。
修复步骤
- 在Android Studio中执行
Build > Clean Project,再执行Rebuild Project,让注解处理器重新生成包含新字段的表配置文件,重新运行应用即可解决新字段写入为null的问题。 - 修正新数据写入的方法调用:id为0的对象是未持久化的新对象,
update()方法是用于更新已存在的记录(会按照id匹配行),插入新记录需要调用organizerItemDao.create(organizerItem),如果需要同时兼容新增和更新场景,使用createOrUpdate()方法。
内容的提问来源于stack exchange,提问作者Tomasz Stępnik
相关产品推荐
相关产品推荐

