【问题标题】:Room Relation Specify Column Names When Extending房间关系在扩展时指定列名
【发布时间】:2020-10-26 20:48:50
【问题描述】:

我正在处理我的房间数据库中的一些数据集,我的方法是创建一个表,其中包含有关名为DatasetInfo 的数据集的信息,该表存储名称、存储的值类型、id 等内容;还有第二个表,我将值存储在 3 列中:(id、date、value)。这个有序的三元组被定义为DatasetValue 实体。在这里,(date, value) 是我要绘制的有序对。

要绘制这些有序对,我必须将它们转换为Entry 对象列表,其中Entry 采用值xy。查询我的数据库并简单地询问List<Entry> 是最有意义的,因为现在我要求List<DatasetValue>,然后我必须将该结果映射到List<Entry>,这是不必要的。

我查询数据集信息表DatasetInfo如下:

data class DatasetWithValues(
    @Embedded
    var datasetInfo: DatasetInfo,
    @Relation(
        parentColumn = DATASET_COLUMN_DATASET_ID,
        entityColumn = VALUES_COLUMN_ID,
        entity = DatasetValue::class,
    )
    var values : List<Entry>
)

现在,正如我上面所说,Entry 具有值 xyDataset 将它们称为 datevalue。当然,当我要求这种关系时,它会失败,因为它不知道如何将具有 iddatevalue 列的表中的值分配给采用 xy。所以,我定义了一个新类:

class DatasetEntry(
    @ColumnInfo(name = "date") 
    var date : Float,
    @ColumnInfo(name = "value") 
    val value : Float
) : Entry(date, value)

然后进行如下调整:

//var values : List<Entry>
var values : List<DatasetEntry> 

这没什么。代码无法编译,因为:

SQL 错误或缺少数据库(没有这样的列:x)

好吧,如果我改写:

class DatasetEntry(
    @ColumnInfo(name = "date")
    var date : Float,
    @ColumnInfo(name = "value")
    val value : Float
) : Entry(){
    init{
        x = date
        y = value
    }
}

这也无济于事,同样的错误。即使我删除了init 电话,它仍然需要x

情节变厚了,因为Entry 内部我可以看到x 被声明为私有。所以我完全不知道这里发生了什么。 Room 怎么知道要找x?除了将表中的列重命名为 xy 之外,还有什么解决方法吗?

【问题讨论】:

    标签: kotlin android-room


    【解决方案1】:

    除了将表中的列重命名为 x 和 y 之外,还有其他解决方法吗?

    如果您有这样的选择,那将是最简单的。您仍然可以考虑一些选择:

    1.将 Room 的结果映射到需要的结果

    所以,您向 Room 索要一些 raw 的结果,然后将其映射到 ready 之一。为此,您添加 2 个类:

    data class DatasetWithValuesRaw(
        @Embedded
        var datasetInfo: DatasetInfo,
        @Relation(
            parentColumn = DATASET_COLUMN_DATASET_ID,
            entityColumn = VALUES_COLUMN_ID,
        )
        var values : List<DatasetValue>
    )
    
    data class DatasetWithValuesReady(
        var datasetInfo: DatasetInfo,
        var values : List<Entry>
    )
    

    假设你有一个 dao 方法:

    Query("select * ....")
    fun getRawData(): List<DatasetWithValuesRaw>
    

    对于您使用的映射:

    fun getReadyData() = 
       getRawData().map { item -> 
        DatasetWithValuesReady(item.datasetInfo, 
           item.values.map { Entry(x = it.date, y = it.value) 
       }) }
    

    2。用显式查询替换 Room 的 @Relation

    这不是您真正想要的,但仍然是一种选择。 使用这样的类:

    data class DatasetWithSeparateValues(
        @Embedded
        var datasetInfo: DatasetInfo,
        @Embedded
        var value : Entry // <----- it's not a list, just a single value
    )
    

    在您的 dao 中,您使用明确的列名(xy)设置查询。类似的东西:

    Query("SELECT *, values.date as x, values.value as y FROM dataset LEFT JOIN values on dataset.DATASET_COLUMN_DATASET_ID = values.VALUES_COLUMN_ID")
    fun getData(): List<DatasetWithSeparateValues>
    

    因此,您将获得一个列表,但如果有一个包含 5 个值的数据集,您将在列表中获得 5 个具有相同数据集和单独值的项目。之后,您可以使用 Kotlin 集合的方法(例如groupBy)以某种方式美化结果

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-25
      • 1970-01-01
      • 2019-01-24
      • 1970-01-01
      • 2019-11-29
      • 2012-04-07
      • 2016-03-07
      相关资源
      最近更新 更多