【问题标题】:TypeConverter function never used room databaseTypeConverter 函数从未使用过房间数据库
【发布时间】:2020-08-25 18:48:35
【问题描述】:

我有自定义对象的列表,我想将其保存在数据库中。

所以我必须使用 TypeConverters 来实现这一点。

我的问题是我在实现功能时遇到错误并注意到

从未使用过使用 TypeConverter 注释的函数

这是错误:

A failure occurred while executing org.jetbrains.kotlin.gradle.internal.KaptExecution
error: The columns returned by the query does not have the fields [avatar,email,first_name,id,last_name] in com.hraa.fakeusers.model.UserData even though they are annotated as non-null or primitive. Columns returned by the query: [data]
    public abstract androidx.lifecycle.LiveData<java.util.List<com.hraa.fakeusers.model.UserData>> getUsers();

这是代码:

@Entity(tableName = USER_DATA_TABLE)
data class DataModel(
    val data: List<UserData>,
    val page: Int,
    val per_page: Int,
    val total: Int,
    val total_pages: Int
) {
    @PrimaryKey(autoGenerate = true)
    var id: Int? = null
}

data class UserData(
    val avatar: String,
    val email: String,
    val first_name: String,
    val id: Int,
    val last_name: String
)

class Converters {

    @TypeConverter
    fun toUsersData(value: String): List<UserData> {
        val type = object : TypeToken<List<UserData>>() {}.type
        return Gson().fromJson(value, type)
    }

    @TypeConverter
    fun fromUsersData(usersData: List<UserData>): String {
        return Gson().toJson(usersData)
    }
}

@Database(entities = [DataModel::class], version = 1, exportSchema = false)
@TypeConverters(Converters::class)
abstract class AppDatabase: RoomDatabase() {

    abstract fun dataDao(): DataDao
}

    @Dao
interface DataDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertData(data: DataModel)

    @Delete
    suspend fun deleteData(data: DataModel)

    @Query("SELECT data FROM USER_DATA_TABLE")
    fun getUsers(): LiveData<List<UserData>>
}

注意:toUsersData() 函数从未使用过。我不知道为什么。

【问题讨论】:

    标签: android android-studio android-room


    【解决方案1】:

    注意:toUsersData() 函数从未使用过

    你怎么能确定呢?我的猜测是这个函数可以很好地工作,但是你在这里有两种类型的转换:

    @Query("SELECT data FROM USER_DATA_TABLE")
    fun getUsers(): LiveData<List<UserData>>
    

    转换 #1(行级)。 输入:字符串(保存在 db 中)。输出:数据(列表)。 由于您的 toUsersData() 方法,这应该得到很好的处理(可能不是,我没有检查过,但似乎应该这样做)

    转换#2(行级)。输入:数据(列表)。输出:UserData(根据您想要的返回类型)。因为那个房间不知道如何进行这种转换,所以你有错误。

    要检查您的 toUsersData() 是否真的有效,您可以测试下一个查询:

    @Query("SELECT * FROM USER_DATA_TABLE")
    fun getUsers(): LiveData<List<DataModel>>
    

    如果你的构建成功,那么这个功能就没有问题了。你也可以在 Java 类中找到这个函数,它是在构建过程中由 Room 自动生成的。

    您可以尝试添加另一个数据类:

    data class UserDataList(
        val data: List<UserData>
    )
    

    并将您的数据方法更改为:

    @Query("SELECT data FROM USER_DATA_TABLE")
    fun getUsers(): LiveData<List<UserDataList>>
    

    【讨论】:

    • 关于 toUsersData().. 我在自动生成的类中检查了它,但它不存在,但当我尝试查询时,你给出的查询实际上是存在的。我还像您一样创建了数据类并且它有效!太感谢了。但是你能解释一下为什么以前的方法不起作用吗?我应该将每个自定义对象作为单独的数据类吗?
    • 我认为没有一般规则,您可以为每个用例组合几个选项。您可以选择 - 使用 Converter 并将对象保存为字符串,或者 - 您可以选择单独的 Entity 并将它们与 Room Relations 链接。您可以自定义查询的结果类型,但您应该了解,在某些极端情况下,Room 无法理解如何将原始 SQLite 字段转换为所需的自定义对象。您的用例正是 Room 无法消化的(描述了 Transformation #2)。但我不会根据这个用例做出一些一般性的结论。
    猜你喜欢
    • 2019-07-23
    • 1970-01-01
    • 1970-01-01
    • 2019-08-12
    • 2023-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-11
    相关资源
    最近更新 更多