I am receiving the error
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.
for "settings".
I don't know what I'm doing wrong, since I have a conversor for Settings. In Converters, "fromScore", "toScore", "fromSettings" and "toSettings" are being used. The rest of the methods are greyed out.
Also feel free to suggest other (possibly better) ways than Room to store this data, please. Thanks.
The entity:
@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")
}
}
}
The converters:
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)
}
}
The database entity:
@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
}
}
}
}
Query giving the error:
@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
The 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)
}
Your DAO function is:
suspend fun updateSettings(id: Int, settings: User.Settings)
This takes a single User.Settings
. Given the rest of your code, this might need to take a List<User.Settings>
, to line up with your entity and type converter.
If you are certain that you want a single User.Settings
here, you probably need a converter for a single User.Settings
, akin to what you have for User.Score
. Right now, your type converter only converts a List<User.Settings>
.