Bente61
Bente61

Reputation: 21

Room one-to-many, to many

I am little a bit confused on how i should set up a data class consisting of two lists.

I have a data class looking like this

@Entity(tableName = "recipe")
data class Recipe(
@PrimaryKey(autoGenerate = false)
val recipeName: String,
//val keyIngrediens: List<KeyIngredient>,
//val steps: List<steps>

So for KeyIngrediens i have set it up like this and it works perfectly without problems

@Entity
data class KeyIngredients(
@PrimaryKey(autoGenerate = false)
val title: String,
val image: String,
val undertitle: Int,
val recipeName: String
)

data class RecipeWithkeyIngredients(
@Embedded val recipe: Recipe,
@Relation(
    parentColumn = "recipeName",
    entityColumn = "recipeName"
)
val keyIngredients: List<KeyIngredients>
)

So basically, i got it to work with one list and one object, but Im a bit confused as how i should handle it when i have two lists in a single object. Right now I'm calling RecipeWithKeyIngredients which returns the recipe object with the list of key ingredients, but i don't know how to make it also contain the steps list.

In short it should be like RecipeWithkeyIngredientsANDsteps if that is possible.

Upvotes: 2

Views: 131

Answers (2)

Varsha Kulkarni
Varsha Kulkarni

Reputation: 1564

This is not enough for recipes. A recipe contains many ingredients, an ingredient belongs to many recipes. So it should be handled with many-to-many relationship.

@Entity
data class Recipe(
  @PrimaryKey
  val recipeId: Long,
  val name: String
)

@Entity
data class KeyIngredient(
  @PrimaryKey
  val keyIngredientId: Long,
  val title: String,
  val image: String,
  val undertitle: Int,
)

@Entity
data class Step(
  @PrimaryKey
  val stepId: Long,
  val instruction: String,
  val stepRecipeId: Long
)

@Entity(
  primaryKeys = ["recipeId", "keyIngredientId"]
)
data class RecipeKeyIngredient(     
  val recipeId: Long,
  val keyIngredientId: Long
)

Get the list of ingredients of a recipe

data class RecipeWithIngredients (
    @Embedded
    val recipe: Recipe,
    @Relation(
            parentColumn = "recipeId",
            entity = KeyIngredient::class,
            entityColumn = "ingredientId",
            associateBy = Junction(
                    value = RecipeKeyIngredient::class,
                    parentColumn = "recipeId",
                    entityColumn = "keyIngredientId"
            )
    )
    val keyIngredients: List<KeyIngredient>
)

Get the list of recipes with the same ingredient

data class IngredientWithRecipes(
  @Embedded
  val ingredient: Ingredient,
  @Relation(
        parentColumn = "ingredientId",
        entity = Recipe::class,
        entityColumn = "recipeId",
        associateBy = Junction(
                value = RecipeKeyIngredient::class,
                parentColumn = "ingredientId",
                entityColumn = "recipeId"
        )
  )
  val recipes: List<Recipe>
)

Now you can query database for the result as:

@Dao
interface RecipeKeyIngredientDao {
  @Query("SELECT * FROM Recipe")
  fun getRecipeWithIngredients(): LiveData<List<RecipeWithIngredients>>

  @Query("SELECT * FROM KeyIngredient")
  fun getIngredientWithRecipes(): LiveData<List<IngredientWithRecipes>>
}

For the other part of the question, a recipe typically contains specific set of steps (instructions?) and to define the relationship between recipe and steps you will need nested relationship which defines one-to-many relationship between recipe and steps, and get the recipe from already modelled IngredientsOfRecipe instead of Recipe table which will give recipe with ingredients. Model the same as

data class RecipeWithIngredientsAndSteps(
    @Embedded val recipe: IngredientsOfRecipe
    @Relation(
        entity = Step::class,
        parentColumn = "recipeId",
        entityColumn = "stepRecipeId"
    )
    val steps: List<Step>
)

Query using single transaction as follows

@Transaction
@Query("SELECT * FROM Recipe")
fun getRecipeWithIngredientsAndSteps(): List<RecipeWithIngredientsAndSteps>

Please refer to this

Upvotes: 2

Farees Hussain
Farees Hussain

Reputation: 181

Assuming your Steps data class as follows:

@Entity
data class Steps(
    @PrimaryKay
    val stepName: String,
    val duration: Int,
    val recipeName: String,
    val rank: Int
)
data class RecipeWithKeyIngredientsAndSteps(
    @Embedded recipe: Recipe,
    @Relation(
        parentColumn = "recipeName",
        entityColumn = "recipeName"
    )
    val keyIngredients: List<KeyIngredients>,
    @Relation(
        parentColumn = "recipeName",
        entityColumn = "recipeName"
    )
    val steps: List<Steps>
)

At the end it's still a One-to-N Relationship

Upvotes: 1

Related Questions