首页 > 解决方案 > 带有嵌入式 FK 的 Android Room 数据建模

问题描述

我试图代表以下实体:

这种关系的例子是:

这是我所拥有的:

Warning实体_

@Entity(tableName = WARNING_TABLE, 
        indices = [Index(unique = true, value = [WARNING_TITLE, WARNING_SUBTITILE])]
       )
data class Warning(
        @field:PrimaryKey @ColumnInfo(name = WARNING_ID) var id: String,
        @ColumnInfo(name = WARNING_TITLE) var text1: String,
        @ColumnInfo(name = WARNING_SUBTITILE) var text2: String?,
        @ColumnInfo(name = WARNING_ACTIVE, defaultValue = "0") var active: Boolean = false
)

Action实体_

@Entity(tableName = ACTION_TABLE, 
        indices = [
                    Index(unique = true, value = [ACTION_TEXT]), 
                    Index(unique = true, value = [ACTION_ICON])
                  ]
        )
data class Action(
        @field:PrimaryKey @ColumnInfo(name = ACTION_ID) var id: String,
        @ColumnInfo(name = ACTION_TEXT) var text: String,
        @ColumnInfo(name = ACTION_ICON) var icon: String,
        @ColumnInfo(name = ACTION_ICON_SRC, defaultValue = "$DRAWABLE_SOURCE_RESOURCES") var iconSrc: DrawableSource? = DrawableSource.Resources
)

...以及将两者联系起来的表格,warning_action表格:

@Entity(tableName = WARNING_ACTION_TABLE,
        primaryKeys = [WARNING_ID, ACTION_ID],
        foreignKeys = [
                        ForeignKey(entity = Warning::class,
                                   parentColumns = [WARNING_ID],
                                   childColumns = [WARNING_ID],
                                   onUpdate = ForeignKey.NO_ACTION,
                                   onDelete = ForeignKey.CASCADE),
                        ForeignKey(entity = Action::class,
                                   parentColumns = [ACTION_ID],
                                   childColumns = [ACTION_ID],
                                   onUpdate = ForeignKey.NO_ACTION,
                                   onDelete = ForeignKey.CASCADE)
                      ],
        indices = [Index(ACTION_ID), Index(WARNING_ID)]
)
data class WarningAction(@ColumnInfo(name = ACTION_ID) val action: String,
                               @ColumnInfo(name = WARNING_ID) val warning: String)

现在我想做的是能够加载所有警告及其相关操作(或单个警告及其相关操作)的列表。

这是我到目前为止所拥有的,但它不起作用:

data class WarningWithActions(@Embedded val warning: Warning,
                              @Relation(parentColumn = WARNING_ID,
                                        entityColumn = ACTION_ID,
                                        associateBy = Junction(WarningAction::class))
                              val actions: List<Action>){
    val id get() = Warning.id
}

...在 DAO 中:

@Query("SELECT * FROM '$WARNING_TABLE' WHERE $WARNING_ID = :id")
fun load (id:String): Maybe<WarningWithActions>

我也试过:

data class WarningWithActions(@Embedded val warning: Warning,
                                    @Relation(parentColumn = WARNING_ID,
                                        entity= Action::class,
                                        entityColumn = ACTION_ID,
                                        associateBy = Junction(value = WarningAction::class, parentColumn = WARNING_ID, entityColumn = ACTION_ID))
                                    val actions: List<Action>){
    val id get() = warning.id
}

我得到一个空的动作列表,我很确定我错过了一些告诉房间如何获得这些的东西,但我无法弄清楚我在这里错过了什么。

I've already used Database Inspector and verified that the actions exist, the warnings exist, and the link entries in the link table also exist.

UPDATE:

Turns out the above implementation is correct. The DAO method that was adding the action to the warning had a Single<Long> (RX) return value:

@Transaction
@Query ("INSERT OR REPLACE INTO '$WARNING_ACTION_TABLE' ($WARNING_ID, $ACTION_ID) VALUES (:wid, :aid)")
fun addAction (eid:String, aid:String):Single<Long>

I guess at some point while writing the unit test that tested this, I was distracted and forgot to subscribe()

标签: androidandroid-sqliteandroid-room

解决方案


推荐阅读