Room error: The columns returned by the query does not have the fields

Room error: The columns returned by the query does not have the fields

我制作了一个像图片一样的屏幕。

如您所见,Set information itemsred box

我想将这些数据存储在Room DB

red boxWorkout Class构成,blue boxWorkoutSetInfo class)包含在其中

我只想从 Room 中获取 set information 的列表。

但是我写了一个查询来获取 set information 的列表, 我收到以下错误:

error: The columns returned by the query does not have the fields [id,set,weight,reps] in com.example.lightweight.data.db.entity.WorkoutSetInfo even though they are annotated as non-null or primitive. Columns returned by the query: [sets]
    public abstract androidx.lifecycle.LiveData<java.util.List<com.example.lightweight.data.db.entity.WorkoutSetInfo>> getWorkoutSetInfoList()

和我类似的问题已经有好几个了,但是我还是没能解决。怎样才能只获取集合信息列表?


WorkoutSetInfo

data class WorkoutSetInfo(
    val id: String = UUID.randomUUID().toString(), // For comparison in DiffUtil.
    val set: Int,
    val weight: String = "",
    val reps: String = ""
)

锻炼

@Entity
data class Workout(
    @PrimaryKey(autoGenerate = true)
    val id: Int,
    val title: String = "",
    val unit: String = "kg",
    val memo: String = "",
    var sets: List<WorkoutSetInfo> = emptyList()
)

DAO

@Dao
interface WorkoutDao {
    @Query("SELECT sets FROM Workout")
    fun getWorkoutSetInfoList() : LiveData<List<WorkoutSetInfo>>

    @Insert
    fun insert(workout: Workout)
}

存储库

class WorkoutRepository(private val workoutDao : WorkoutDao, title: String) {
    val workout = Workout(0, title)
    var setInfoList : ArrayList<WorkoutSetInfo> = arrayListOf()
    
    val _items: LiveData<List<WorkoutSetInfo>> = workoutDao.getWorkoutSetInfoList()

    fun add(item: WorkoutSetInfo) {
        setInfoList.add(item)
        workout.sets = setInfoList

        workoutDao.insert(workout)
    }
}

ViewModel

class DetailViewModel(application: Application, title: String) : ViewModel() {
    private val repository: WorkoutRepository

    private lateinit var _items: LiveData<List<WorkoutSetInfo>>
    val items = _items
    private val list: List<WorkoutSetInfo>
        get() = _items.value ?: emptyList()

    init {
        val workoutDao = DetailDatabase.getDatabase(application)!!.workoutDao()
        repository = WorkoutRepository(workoutDao, title)
        _items = repository._items
    }

    fun addDetail() {

        viewModelScope.launch(Dispatchers.IO){
            val item = WorkoutSetInfo(set = list.size+1)
            repository.add(item)
        }
    }
}

已更新

class Converter {
    @TypeConverter
    fun listToJson(value: List<WorkoutSetInfo>) : String {
        return Gson().toJson(value)
    }

    @TypeConverter
    fun jsonToList(value: String) : List<WorkoutSetInfo> {
        return Gson().fromJson(value, Array<WorkoutSetInfo>::class.java).toList()
    }
}

您正试图在列中保存复杂对象的列表。房间不知道怎么保存。

var sets: List<WorkoutSetInfo> = emptyList() <-- 这很复杂

记住房间只是下面的 sqlite,您的实体代表 tables。 Sqlite 识别基本类型,但默认情况下它不能存储复杂对象列表。如果您想将此对象保存在同一个 table.

中,您可以探索 TypeConverters 作为解决方案

请参阅下文,了解使用单独 tables 的关系解决方案:

您在这里寻找的是 one-to-many 关系。一个Workout可以有一个或多个WorkoutSetInfo

在关系数据库的世界中,您可以通过为 WorkoutSetInfo 设置一个单独的 table 来表示这一点,并使用工作表的 id 中的 ID 来创建关系。

@Entity
data class WorkoutSetInfo(
    val id: String = UUID.randomUUID().toString(), // For comparison in DiffUtil.
    val set: Int,
    val weight: String = "",
    val reps: String = "",
    val workoutId: String // <-- this is the id of the workout that this set is associated with
)

完成后,您可以编写连接查询或使用数据对象按定义进行查询 here

你可以有这样的东西:

data class WorkoutWithSets(
    @Embedded val workout: Workout,
    @Relation(
        parentColumn = "id",
        entityColumn = "workoutId"
    )
    val sets: List<WorkoutSetInfo>
)

并使用类似这样的东西来查询它

    @Transaction
    @Query("SELECT * FROM Workout WHERE id = :workoutId")
    fun getWorkoutWithSets(workoutId: String) : LiveData<WorkoutWithSets>

这将给出给定 ID 的锻炼以及与集合 table 中该锻炼 ID 匹配的所有集合。

目前您发布的错误是在选择中找不到集合

data class WorkoutSetInfo(
    val id: String = UUID.randomUUID().toString(), // For comparison in DiffUtil.
    val set: Int,//Add Any value or make it nullable here for get temp rid of this error
    val weight: String = "",
    val reps: String = ""
)

但是作为 Naveeds 的回答,你必须使用 typeConvertor 或者用关系数据库类型解决这个问题 不实现这个类型转换器或关系结构房间会给你错误