Room中@TypeConverter实现String转Date的空安全问题
解决方案
1. 改造TypeConverter实现空安全
修改stringToDate方法,空值、空字符串或解析失败时都返回业务可接受的默认日期(如当前时间),禁止返回null,适配Kotlin非空字段要求:
public class DateTimeConverter { private static final String DATE_PATTERN = Constants.SQLITE_DATE_TIMEFORMAT; @TypeConverter public static Date stringToDate(String value) { // 空值、空白字符串直接返回默认当前时间 if (value == null || value.trim().isEmpty()) { return new Date(); } DateFormat df = new SimpleDateFormat(DATE_PATTERN, Locale.US); try { return df.parse(value); } catch (ParseException e) { e.printStackTrace(); // 解析异常兜底返回默认时间 return new Date(); } } @TypeConverter public static String dateToString(Date value) { DateFormat df = new SimpleDateFormat(DATE_PATTERN, Locale.US); // 非空兜底,避免极端场景下Date为空写入null到数据库 return value == null ? df.format(new Date()) : df.format(value); } }
2. 给Entity字段加数据库非空约束
在writeDate字段上添加@ColumnInfo(nullable = false)注解,强制数据库层面该字段不允许为空,避免脏数据写入:
@Entity @TypeConverters(DateTimeConverter::class) data class Entity( @ColumnInfo(nullable = false) var writeDate: Date = Date() // java.util.Date )
3. 排查null值产生的根因
即使数据库现有数据该字段都不为空,仍可能触发空值传入的场景:
- 数据库升级新增
writeDate字段时,没有给旧数据设置默认值,需要在迁移SQL中补充非空约束和默认值,示例:ALTER TABLE 你的表名 ADD COLUMN writeDate TEXT NOT NULL DEFAULT '对应格式的默认时间字符串' - 自定义查询语句为投影查询,漏写了
writeDate字段,Room会自动给未查询的字段传入null - 插入数据的逻辑中存在手动给
writeDate赋值为null的分支
注意事项
SimpleDateFormat不是线程安全的,当前实现每次调用创建新实例的方式避免了线程安全问题,性能损耗可忽略,适配Room的调用场景。
内容的提问来源于stack exchange,提问作者clamentjohn
相关产品推荐
相关产品推荐

