Hoinzey

Javascript. Kotlin. Android. Java

Android: Room many to many objects

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.

Animal
Group
                    
    @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.


Animal to Group Entity
Group with animals
Animal with groups
                            
                    
    @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
)