'How to update relation objects in Android Room

I am using Room in Android for persistence and have a class Profile which has relations to Place and Timeframe. I also have a ProfileWithRelations class that stored not only the place and timeframe IDs but also the objects. I am using this query in the DAO to get Livedata from the DB and get updates by an observer if something has changed:

@Transaction
@Query("SELECT * FROM profile")
fun getAllWithRelations(): Flow<List<ProfileWithRelations>>

So far so good. If a profile of the ProfileWithRelations is changed (i.e. the place is removed), the observer is triggered and the profile object in ProfileWithRelations is updated. However, the place object of the ProfileWithRelations does not get updated (should change to null as well).

What can I do to automatically update the other objects in ProfileWithRelations if the profile changes?

Profile Entity:

@Entity(
    indices = [Index(value= ["title"], unique = true)],
    foreignKeys = [ForeignKey(
        entity = Place::class,
        parentColumns = arrayOf("place_uid"),
        childColumns = arrayOf("place_id"),
        onDelete = ForeignKey.CASCADE
    ), ForeignKey(
        entity = Timeframe::class,
        parentColumns = arrayOf("timeframe_uid"),
        childColumns = arrayOf("timeframe_id"),
        onDelete = ForeignKey.CASCADE
    )]
)
data class Profile(
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "profile_uid")
    val profileUID: Long,

    var title: String,

    @ColumnInfo(name="place_id")
    var placeId: Long?,

    @ColumnInfo(name="timeframe_id")
    var timeframeId: Long?,

    var active: Boolean
): Serializable

ProfileWithRelations:

data class ProfileWithRelations (
    @Embedded
    val profile: Profile,

    @Relation(parentColumn = "profile_uid", entityColumn = "place_uid")
    val place: Place?,

    @Relation(parentColumn = "profile_uid", entityColumn = "timeframe_uid")
    val timeframe: Timeframe?,

    @Relation(
        parentColumn = "profile_uid",
        entityColumn = "detail_action_uid"
    )
    val actions: List<DetailAction>
): Serializable

Place Entity:

@Entity(indices = [Index(value= ["title", "address"], unique = true)])
data class Place (
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "place_uid")
    val placeUID: Long,

    var title: String,

    var address: String?,

    val latitude: String?,

    val longitude: String?,

    var range: Int
): Serializable

Timeframe Entity:

@Entity
data class Timeframe(
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "timeframe_uid")
    val timeframeUID: Long,

    var from: Time,

    var to: Time,

    @ColumnInfo(name="am_pm")
    val amPm: Boolean,

    var weekdays: Set<Weekday>
): Serializable


Solution 1:[1]

ProfileWithRelations is not a table/entity, and is really only an extract from the databas. Changes to ProfileWithRelations are not applied to the underlying database.

As such you should apply any changes and then, (perhaps optionally) extract again via getAllWithRelations, probably with the observers observing the tables that form the relationship rather than the extract (depending upon the extract or not extract option).

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 MikeT