【问题标题】:Android Room - error: Cannot figure out how to save this field into databaseAndroid Room - 错误:无法弄清楚如何将此字段保存到数据库中
【发布时间】:2018-11-04 01:31:30
【问题描述】:

详细日志

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;

我有一个字段为的实体

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

为什么 Room 不能保留 Date 对象?什么是日期的最佳转换器?

【问题讨论】:

  • 您确定您提供了DateTypeConverter 吗?如果是,请将其与您的问题一起发布。

标签: java android kotlin android-room


【解决方案1】:

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

例如,如果我们想持久化 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 定义的转换器:

AppDatabase.java

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

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

【讨论】:

【解决方案2】:
    // 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() {

【讨论】:

    【解决方案3】:

    以上所有答案都是针对字符串列表的。但下面可以帮助您找到对象列表的转换器。

    只需在“YourClassName”的位置添加您的 Object 类。

     @TypeConverter
            public String fromValuesToList(ArrayList<**YourClassName**> value) {
                if (value== null) {
                    return (null);
                }
                Gson gson = new Gson();
                Type type = new TypeToken<ArrayList<**YourClassName**>>() {}.getType();
                return gson.toJson(value, type);
            }
        
            @TypeConverter
            public ArrayList<**YourClassName**> toOptionValuesList(String value) {
                if (value== null) {
                    return (null);
                }
                Gson gson = new Gson();
                Type type = new TypeToken<List<**YourClassName**>>() {
                }.getType();
                return gson.fromJson(value, type);
            }
    

    【讨论】:

      【解决方案4】:

      在Kotlin中,需要在两个文件中添加@TypeConverters

      1. RoomDatabase扩展的数据库类
      @Database(entities = [ToDo::class], version = 1, exportSchema = false)
      @TypeConverters(DateConverter::class)
      abstract class AppDatabase : RoomDatabase() {
      
          abstract fun todoDao(): ToDoDao
      
          companion object {
              @Volatile private var instance: AppDatabase? = null
      
              fun getDatabase(context: Context): AppDatabase =
                  instance ?: synchronized(this) { instance ?: buildDatabase(context).also { instance = it } }
      
              private fun buildDatabase(appContext: Context) =
                  Room.databaseBuilder(appContext, AppDatabase::class.java, "todo")
                      .fallbackToDestructiveMigration()
                      .build()
          }
      
      }
      
      1. @Entity声明的数据类,需要为Date添加DateConverter
      @Entity(tableName = "todo")
      data class ToDo(
          @PrimaryKey
          val id: Int,
          val title: String,
          val description: String,
          val time: String,
          val date: String,
          val types: Int,
          @TypeConverters(DateConverter::class)
          val date_time: Date,
          val created: String
      )
      

      日期转换器类

      import androidx.room.TypeConverter
      import java.util.*
      
      class DateConverter {
      
          @TypeConverter
          fun toDate(timestamp: Long): Date {
              return Date(timestamp)
          }
      
          @TypeConverter
          fun toTimestamp(date: Date): Long {
              return date.time
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-10-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-07-21
        • 1970-01-01
        相关资源
        最近更新 更多