Android: Room many to many objects
25th April 2023
I previously wrote a post on one to many relationships in Android's Room database. This post will look at many-to-many relationships.
There are plenty of scenarios where you build a database schema that has a many-to-many relationship. In this example I am using Animals being put into groups, imagine a farmer organising their herd. An animal can be in many groups. A group can have many animals. Modelled below.
@Entity(tableName = "animals")
data class AnimalEntity(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "animalid")
var animalId: Long = 0,
var ref: String
)
@Entity(tableName = "groupings",
indices = [Index(value = ["name"], unique = true)])
data class GroupingEntity(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "groupid")
var groupId: Long = 0,
var name: String
)
The first step is to create a table which will hold both sets of IDs. This table will then be used within 2 data classes to give us either our group with the list of animals, or our animal with its list of groups.
The AnimalToGroupingEntity
has primary keys of both animalid
and groupid
. The 2 supporting data classes have their parent and entity column flipped
depending on which result they are looking for. You can google the annotations if you want. Just copy and paste though
and you'll have a working many-to-many setup.
@Entity(tableName = "animalstogroups",
primaryKeys = ["animalid", "groupid"],
foreignKeys = [ForeignKey(
entity = GroupingEntity::class,
parentColumns = arrayOf("groupid"),
childColumns = arrayOf("groupid"),
onDelete = CASCADE)])
data class AnimalToGroupingEntity(
@ColumnInfo(name = "animalid")
val animalId: Long,
@ColumnInfo(name = "groupid")
val groupId: Long
)
data class GroupWithAnimals (
@Embedded val group: GroupingEntity,
@Relation(
parentColumn = "groupid",
entityColumn = "animalid",
associateBy = Junction(AnimalToGroupingEntity::class))
val animals: List)
data class AnimalToGroups(
@Embedded val animal: AnimalEntity,
@Relation(
parentColumn = "animalid",
entityColumn = "groupid",
associateBy = Junction(AnimalToGroupingEntity::class)
)
val groups: List
)