Java Android Room - 错误:无法弄清楚如何将此字段保存到数据库中

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/50515820/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 23:40:02  来源:igfitidea点击:

Android Room - error: Cannot figure out how to save this field into database

javaandroidkotlinandroid-room

提问by Arka Prava Basu

Detailed log

详细日志

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;

I have an entity with a field as

我有一个带有字段的实体

var mStartTime : Date = Date() // java.util.Date

Why cant Room persist Date objects? What can be best converter for Date?

为什么 Room 不能持久化 Date 对象?什么可以是日期的最佳转换器?

采纳答案by Alexey Romanov

Dateis exactly the example given in https://developer.android.com/training/data-storage/room/referencing-data.

Date正是https://developer.android.com/training/data-storage/room/referencing-data 中给出的示例。

For example, if we want to persist instances of Date, we can write the following TypeConverter to store the equivalent Unix timestamp in the database:

public class Converters {
    @TypeConverter
    public static Date fromTimestamp(Long value) {
        return value == null ? null : new Date(value);
    }
    @TypeConverter
    public static Long dateToTimestamp(Date date) {
        return date == null ? null : date.getTime();
    }
}

The preceding example defines 2 functions, one that converts a Date object to a Long object and another that performs the inverse conversion, from Long to Date. Since Room already knows how to persist Long objects, it can use this converter to persist values of type Date.

Next, you add the @TypeConverters annotation to the AppDatabase class so that Room can use the converter that you've defined for each entity and DAO in that AppDatabase:

AppDatabase.java

@Database(entities = {User.class}, version = 1)
@TypeConverters({Converters.class})
public abstract class AppDatabase extends RoomDatabase {
    public abstract UserDao userDao();
}

例如,如果我们想要持久化 Date 的实例,我们可以编写以下 TypeConverter 来在数据库中存储等效的 Unix 时间戳:

public class Converters {
    @TypeConverter
    public static Date fromTimestamp(Long value) {
        return value == null ? null : new Date(value);
    }
    @TypeConverter
    public static Long dateToTimestamp(Date date) {
        return date == null ? null : date.getTime();
    }
}

前面的示例定义了 2 个函数,一个将 Date 对象转换为 Long 对象,另一个执行从 Long 到 Date 的逆转换。由于 Room 已经知道如何持久化 Long 对象,它可以使用这个转换器来持久化 Date 类型的值。

接下来,您将 @TypeConverters 注释添加到 AppDatabase 类,以便 Room 可以使用您为该 AppDatabase 中的每个实体和 DAO 定义的转换器:

应用数据库.java

@Database(entities = {User.class}, version = 1)
@TypeConverters({Converters.class})
public abstract class AppDatabase extends RoomDatabase {
    public abstract UserDao userDao();
}

A side note: java.util.Dateis considered to be badly designed (and java.util.Calendaris much worse). If you have any non-trivial date-time logic and can get away with API level 26 (Java 8 on desktop), it's generally better to use java.timepackage. And if you can't, see https://github.com/JakeWharton/ThreeTenABPfor a backport.

旁注:java.util.Date被认为设计不当(而且java.util.Calendar更糟)。如果您有任何重要的日期时间逻辑并且可以摆脱 API 级别 26(桌面上的 Java 8),通常最好使用java.timepackage。如果不能,请参阅https://github.com/JakeWharton/ThreeTenABP以获取反向移植。

回答by BroPage

    // Java code will not convert to Kotlin very 
    // well so here is the Kotlin: Converter 
    // class

    public class Converters {
        @TypeConverter
        fun fromTimestamp( value: Long?) : 
                       java.sql.Date {
            return java.sql.Date(value ?: 0)
        }
        @TypeConverter
        fun dateToTimestamp(date :java.sql.Date?) 
                                 :Long {
            return date?.getTime() ?: 0
       }

    // Here is the type converters example in 
    // Kotlin
    @Database(entities = [DbNasaPictures::class], 
              version = 2)
    @TypeConverters(Converters::class)
    abstract class PicturesDatabase: 
                     RoomDatabase() {