Android Room报错:无法存储Date字段,求最佳类型转换器方案
问题根源:Room只认SQLite原生类型
Room作为SQLite的封装库,默认只支持SQLite内置的基础数据类型——比如int、long、String、byte[]这些。而你用的java.util.Date属于Java的自定义对象,SQLite本身没有对应的存储类型,Room自然不知道该怎么把它映射到数据库字段里,所以就会抛出你看到的错误:
error: Cannot figure out how to save this field into database. You can consider adding a type converter for it. private final java.util.Date mTime = null;
针对Date的最佳类型转换器:转成Long(时间戳)
最稳妥、高效的方案是把Date转换成SQLite支持的long类型(也就是时间戳,毫秒数),这也是官方推荐的做法。原因很简单:
- 存储效率高:
long对应SQLite的INTEGER类型,占用空间小,查询速度快 - 无格式/时区问题:不像存字符串那样可能因为格式不统一或时区偏移导致解析错误
- 转换逻辑简单,不容易出bug
具体实现步骤:
创建类型转换器类
写一个普通类,用@TypeConverter注解标记转换方法:class DateConverter { @TypeConverter fun fromDateToLong(date: Date?): Long? { return date?.time } @TypeConverter fun fromLongToDate(timestamp: Long?): Date? { return timestamp?.let { Date(it) } } }这两个方法分别负责把
Date转成Long(存库),以及把Long转回Date(读库)。在Room数据库类中启用转换器
在你的@Database注解的类上,加上@TypeConverters注解,指定刚才写的转换器类:@Database(entities = [YourEntity::class], version = 1) @TypeConverters(DateConverter::class) abstract class AppDatabase : RoomDatabase() { // DAO定义 abstract fun yourDao(): YourDao }正常使用Date字段
现在你的实体类里的var mStartTime: Date = Date()就能正常被Room持久化了,不需要做其他修改。
额外提醒
如果你之后迁移到Java 8的java.time API(比如LocalDate、LocalDateTime),Room也有对应的内置转换器,不过针对你目前用的java.util.Date,上面的方案就是最优解。
内容的提问来源于stack exchange,提问作者Arka Prava Basu

