房间错误:查询返回的列没有字段

yby*_*byb 4 android kotlin android-room

在此输入图像描述

我制作了一个如图所示的屏幕。

如您所见,它们Set information items位于red box.

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

red box由 组成Workout Class,其中包含blue box( )。WorkoutSetInfo 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()
Run Code Online (Sandbox Code Playgroud)

我的类似问题已经有好几个了,但我还是没能解决。如何只获取设置信息的列表?


锻炼设置信息

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

锻炼

@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()
)
Run Code Online (Sandbox Code Playgroud)

DAO

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

    @Insert
    fun insert(workout: Workout)
}
Run Code Online (Sandbox Code Playgroud)

存储库

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

视图模型

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)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

更新

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()
    }
}
Run Code Online (Sandbox Code Playgroud)

Nav*_*eed 5

您正在尝试将复杂对象的列表保存在列中。Room不知道如何保存它。

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

请记住,room 下面只是 sqlite,您的实体代表表。Sqlite 可以识别基本类型,但默认情况下它无法存储复杂对象的列表。如果您想将此对象保存在同一个表中,您可以探索TypeConverters作为解决方案。

请参阅下面的使用单独表的关系解决方案:

您在这里寻找的是一对多关系。单个Workout可以有一个或多个WorkoutSetInfo

在关系数据库的世界中,您可以通过使用单独的表来表示这一点,并使用工作的WorkoutSetInfoid来创建关系。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
)
Run Code Online (Sandbox Code Playgroud)

完成后,您可以编写联接查询或使用数据对象进行查询,如此处定义

你可以有这样的东西:

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

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

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

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