Android Room, relation with polymorphic entities

Viewed 21

Here is simplified example of my JSON response :

[
    {
      "id": 1,
      "accountName": "Alex Terrible",
      "socialNetworks": [
         {
            "id": 1,
            "type": "instagram",
            "instagramUrl": "https://instagram.com/alexterribleofficial"
         }
      ]
   },
   {
      "id": 2,
      "accountName": "Ivan Boring",
      "socialNetworks": [
         {
            "id": 2,
            "type": "facebook",
            "facebooName": "Ivan Boring"
         }
      ]
   }
]

It is array of people with id, accountName and socialNetworks. Social networks have a different type. I already have read about polymorphism with single or separate tables here: https://commonsware.com/Room/pages/chap-poly-001.html. I would like variant with separate tables, because in case types count will be increased to 10 single table looks awful. So my schemas :

interface SocialNetwork {
    fun getSocialNetworkType(): String
}

@Entity(tableName = "instagram_table")
data class InstagramNetwork(
    @ColumnInfo(name = "id") @PrimaryKey var id: Int,
    @ColumnInfo(name = "type") var type: String,
    @ColumnInfo(name = "instagramUrl") val instagramUrl: String,
) : SocialNetwork {
    override fun getSocialNetworkType() = type
}

@Entity(tableName = "facebook_table")
data class FacebookNetwork(
    @ColumnInfo(name = "id") @PrimaryKey var id: Int,
    @ColumnInfo(name = "type") var type: String,
    @ColumnInfo(name = "facebooName") val facebooName: String,
) : SocialNetwork {
    override fun getSocialNetworkType() = type
}

Let's say it works but next I need to link person class with social network. I would like something like that :

@Entity(tableName = "people_table")
data class Person(
    @ColumnInfo(name = "id") @PrimaryKey val id: Int,
    @ColumnInfo(name = "account_name") val accountName: String,
    @Ignore val socialNetworks: List<SocialNetwork>
) {
    constructor(id: Int, accountName: String): this(id, accountName, arrayListOf())
}

data class PersonWithSocialNetwotks(
    @Embedded
    val person: Person,

    @Relation(
        parentColumn = "id",
        entity = SocialNetwork::class,
        entityColumn = "id",
        associateBy = Junction(
            value = PersonSocialNetwork::class,
            parentColumn = "person_id",
            entityColumn = "social_network_id"
        )
    )
    val socialNetwotks: List<SocialNetwork>
)

@Entity(
    primaryKeys = ["person_id", "social_network_id"],
    indices = [Index(value = ["social_network_id"])]
)
data class PersonSocialNetwork(
    @ColumnInfo(name = "person_id") val personId: Int,
    @ColumnInfo(name = "social_network_id") val socialNetworkId: Int
)

Of course it is not correct example. There is no SocialNetwork table and raletion is broken. My question is how can I store data like this more elegant? In polymorphism with separate tables examples all selects is writen by hands but I would like room get all data without my assistence. I already achive it on backend with SQLAlchemy and hope room could do the same.

Thanks for help.

0 Answers
Related