Search code examples
androidandroid-studioandroid-roomandroid-database

(Android) How to match child ID to parent in one-to-many relationship


enter image description here

I'm working on an image-like, one-to-many database.

To explain the flow of functions, WorkoutSetInfo is added to the list whenever the Add button is pressed. (It is not inserted into DB.)

Finally, when the Save button is pressed, the Workout and WorkoutSetInfo list are inserted into the DB.

I have completed setting up the relationship between Workout and WorkoutSetInfo, but I don't know how to match the ID of each Workout with Id(parendWorkoutId) of WorktoutSetInfo.

(Now, all IDs of parendWorkoutId are set to 1.)

How should I set it up?


Workout

@Entity
data class Workout(
    @PrimaryKey(autoGenerate = true)
    val workoutId: Long,
    val title: String = "",
    var unit: String = "kg",
    val memo: String = "",
)

WorkoutSetInfo

@Entity(
    foreignKeys = [
        ForeignKey(
            entity = Workout::class,
            parentColumns = arrayOf("workoutId"),
            childColumns = arrayOf("parentWorkoutId"),
            onDelete = ForeignKey.CASCADE
        )
    ]
)
data class WorkoutSetInfo(
    @PrimaryKey(autoGenerate = true)
    val id: Long = 0,
    val set: Int,
    var weight: String = "",
    var reps: String = "",
    val parentWorkoutId: Long = 1 // How do I set this up?
)

WorkoutWithSets

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

Repository

class WorkoutRepository(private val workoutDao : WorkoutDao, title: String) {
    val workout = Workout(0, title)
    private val setInfoList = ArrayList<WorkoutSetInfo>()
    
    fun add() {
        val item = WorkoutSetInfo(set = setInfoList.size + 1)
        setInfoList.add(item)
    }

    fun delete() {
        if(setInfoList.size != 0)
            setInfoList.removeLast()
        return
    }

    fun save() {
        workoutDao.insertWorkout(workout)
        workoutDao.insertSetInfoList(setInfoList)
    }
}

Solution

  • In the workoutDao interface/abstract class, have the insertWorkout function return a Long. This will be the id of the inserted Workout or -1 if the insert was ignored.

    Retrieve/Use this returned value and use it to set the parentWorkoutId of each element in setInfoList within the save function.

    • of course if the value is -1 then you should handle this appropriately as the Workout would not have been inserted.

    E.G.

    if you change parentWorkoutId from val to var then the save function could be something like:-

    fun save(): Boolean {
        var rv = false /* indicate nothing done as insert was ignored */
        val id = workoutDao.insertWorkout(workout)
        if (id > 0) {
            rv = true
            for (wi in setInfoList) {
                wi.parentWorkoutId = id
            }
            workoutDao.insertSetInfoList(setInfoList)
        }
        return rv
    }