在 Kotlin 中使用 TypeConverter (GSON) 处理带有自定义对象的 Room 时出错

问题描述 投票:0回答:1

我收到错误消息

Query method parameters should either be a type that can be converted into a database column or a List / Array that contains such type. You can consider adding a Type Adapter for this.
“设置”

我不知道我做错了什么,因为我有一个设置转换器。 在转换器中,使用“fromScore”、“toScore”、“fromSettings”和“toSettings”。其余方法均呈灰色。

也请随意建议除 Room 之外的其他(可能更好)方法来存储此数据。谢谢。

实体:

@Entity(tableName = "user_table")
data class User(
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "id") val id: Int = 0,
    @ColumnInfo(name = "score") val score: Score = Score(),
    @ColumnInfo(name = "settings") val settings: List<Settings> = emptyList(),
) {

    data class Score(
        val score: Int = 0,
        val correctAnswers: Int = 0,
    )

    data class Settings(
        val name: String = "",
        val mode: Set<GameMode> = emptySet(),
        val selectionMode: Boolean = false,
        val questionLimit: QuestionLimit = QuestionLimit.FIFTEEN,
        val continents: List<Continent> = emptyList(),
    ) {
        enum class GameMode {
            COUNTRY_CAPITAL, CAPITAL_COUNTRY
        }

        enum class QuestionLimit(val number: String) {
            FIFTEEN("15"),
            THIRTY("30"),
            FIFTY("50"),
            MAX("Max")
        }
    }
}

转换器:

class Converters {

    private val gson = Gson()

    // SCORE
    @TypeConverter
    fun fromScore(value: User.Score): String {
        return gson.toJson(value)
    }

    @TypeConverter
    fun toScore(value: String): User.Score {
        return gson.fromJson(value, User.Score::class.java)
    }

    // SETTINGS
    @TypeConverter
    fun fromSettings(value: List<User.Settings>): String {
        return gson.toJson(value)
    }

    @TypeConverter
    fun toSettings(value: String): List<User.Settings> {
        val type = object : TypeToken<List<User.Settings>>() {}.type
        return gson.fromJson(value, type)
    }

    // QUESTION LIMIT
    @TypeConverter
    fun fromQuestionLimit(value: QuestionLimit): String {
        val type = object : TypeToken<QuestionLimit>() {}.type
        return gson.toJson(value, type)
    }

    @TypeConverter
    fun toQuestionLimit(value: String): QuestionLimit {
        val type = object : TypeToken<QuestionLimit >() {}.type
        return gson.fromJson(value, type)
    }

    // CONTINENT
    @TypeConverter
    fun fromContinentList(value: List<Continent>): String {
        val type = object : TypeToken<List<Continent>>() {}.type
        return gson.toJson(value, type)
    }

    @TypeConverter
    fun toContinentList(value: String): List<Continent> {
        val type = object : TypeToken<List<Continent>>() {}.type
        return gson.fromJson(value, type)
    }

    // GAME MODE SET
    @TypeConverter
    fun fromGameModeSet(value: Set<GameMode>): String {
        val type = object : TypeToken<Set<GameMode>>() {}.type
        return gson.toJson(value, type)
    }

    @TypeConverter
    fun toGameModeSet(value: String): Set<GameMode> {
        val type = object : TypeToken<Set<GameMode>>() {}.type
        return gson.fromJson(value, type)
    }
}

数据库实体:

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

    companion object {
        @Volatile
        private var INSTANCE: AppDatabase? = null

        fun getDatabase(context: Context): AppDatabase {
            return INSTANCE ?: synchronized(this) {
                val instance = Room.databaseBuilder(
                    context.applicationContext,
                    AppDatabase::class.java,
                    "app_database"
                ).build()
                INSTANCE = instance
                instance
            }
        }
    }
}

查询给出错误:

    @androidx.room.Query(value = "UPDATE user_table SET settings = :settings WHERE id = :id")
    @org.jetbrains.annotations.Nullable
    public abstract java.lang.Object updateSettings(int id, @org.jetbrains.annotations.NotNull

DAO:

@Dao
interface UserDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun setUser(user: User)

    @Query("SELECT * FROM user_table WHERE id = :id LIMIT 1")
    suspend fun getUserById(id: Int): User?

    @Query("UPDATE user_table SET settings = :settings WHERE id = :id")
    suspend fun updateSettings(id: Int, settings: User.Settings)

    @Query("UPDATE user_table SET score = :score WHERE id = :id")
    suspend fun updateScore(id: Int, score: User.Score)
}
android kotlin type-conversion gson android-room
1个回答
0
投票

您的 DAO 功能是:

suspend fun updateSettings(id: Int, settings: User.Settings)

这需要一个

User.Settings
。鉴于代码的其余部分,这可能需要使用
List<User.Settings>
来与您的实体和类型转换器保持一致。

如果您确定这里需要一个

User.Settings
,您可能需要一个用于单个
User.Settings
的转换器,类似于
User.Score
的转换器。现在,您的类型转换器仅转换
List<User.Settings>

© www.soinside.com 2019 - 2024. All rights reserved.