I am working with room persistence library in android, i would appreciate if someone can help me in using foreign key, how to get data by using foreign key.
-
7There is an excellent [Blog post](https://android.jlelse.eu/android-architecture-components-room-relationships-bf473510c14a) regarding Usage of Room Relationships with foreignKeys – Rinav Nov 27 '17 at 15:27
-
thanks, the post is really nice. – Nirmal Prajapat Nov 28 '17 at 05:12
-
Happy to Help :) – Rinav Nov 28 '17 at 05:14
-
one more thing, Is it mandatory to create multiple DAOs when we’re creating multiple entities.If no then please tell how to implement multiple DAOs in a single one. – Nirmal Prajapat Nov 28 '17 at 05:18
-
1It is better when you create multiple DAO's as it separates each other. It's one of the important rule in [SOLID Principles](https://academy.realm.io/posts/donn-felker-solid-part-1) – Rinav Nov 28 '17 at 05:25
-
yeah it'll be convenient to use multiple DAOs instead of single. but we can use single DAO as well . . . Right??? – Nirmal Prajapat Nov 28 '17 at 05:34
-
I haven't tried it, so cant comment on it Sorry – Rinav Nov 28 '17 at 05:40
-
@NirmalPrajapat it is not a good pratice to use one DAO ! Use one DAO for one entity. This way it is easier to read the code too. – Dagnogo Jean-François Jun 29 '18 at 14:54
-
1https://medium.com/@magdamiu/android-room-persistence-library-relations-75bbe02e8522 check this – Mar 18 '19 at 07:08
-
I am, for testing some room things, currently using one DAO with multiple async tasks inside that handle different inserts. Works well. @NirmalPrajapat – lucidbrot May 09 '19 at 05:23
3 Answers
Just to summarize the above posts for future readers:
The foreign key syntax in Kotlin is
@Entity(foreignKeys = arrayOf(ForeignKey(entity = ParentClass::class,
parentColumns = arrayOf("parentClassColumn"),
childColumns = arrayOf("childClassColumn"),
onDelete = ForeignKey.CASCADE)))
The foreign key syntax in Java is:
@Entity(foreignKeys = {@ForeignKey(entity = ParentClass.class,
parentColumns = "parentClassColumn",
childColumns = "childClassColumn",
onDelete = ForeignKey.CASCADE)
})
Note: foreignKeys is an array, so in Java enclose @ForeignKey elements in { and }
You can refer to the official documentation for more information. https://developer.android.com/reference/androidx/room/ForeignKey
-
10Thank you for taking your time to actually present a show and tell. While others are busy just throwing links to content that may eventually change in the future. – TheRealChx101 May 17 '20 at 15:14
-
1
-
-
Is it compulsory to use `foreignKeys` inside `Entity` or can we use `@Relation` annotation only? – Sumit Shukla Mar 22 '21 at 04:38
Here how you can define and access a One-to-many (Foreign Key) relationship in Android Jetpack Room. Here the Entities are Artist
and Album
and the foreign key is Album.artist
@Entity
data class Artist(
@PrimaryKey
val id: String,
val name: String
)
@Entity(
foreignKeys = [ForeignKey(
entity = Artist::class,
parentColumns = arrayOf("id"),
childColumns = arrayOf("artist"),
onDelete = ForeignKey.CASCADE
)]
)
data class Album(
@PrimaryKey
val albumId: String,
val name: String,
@ColumnInfo(index = true)
val artist: String
)
then the embedded object (read official Android documentation: Define relationships between objects)
data class ArtistAndAlbums(
@Embedded
val artist: Artist,
@Relation(
parentColumn = "id",
entityColumn = "artist"
)
val albums: List<Album>
)
And finally the DAO
@Dao
interface Library {
@Insert
suspend fun save(artist: Artist)
@Insert
suspend fun save(vararg album: Album)
@Transaction
@Query("SELECT * FROM artist")
suspend fun getAll(): List<ArtistAndAlbums>
@Transaction
@Query("SELECT * FROM artist WHERE id = :id")
suspend fun getByArtistId(id: String): ArtistAndAlbums
}
trying this out, (all these operations happens inside a Coroutine)
// creating objects
val artist = Artist(id="hillsongunited", name="Hillsong United" )
val artist2 = Artist(id="planetshakers", name="Planet Shakers" )
val album1 = Album(albumId = "empires", name = "Empires", artist = artist.id)
val album2 = Album(albumId = "wonder", name = "Wonder", artist = artist.id)
val album3 = Album(albumId = "people", name = "People", artist = artist.id)
val album4 = Album(albumId = "rain", name = "Rain", artist = artist2.id)
val album5 = Album(albumId = "itschristmas", name = "Its Christmas", artist = artist2.id)
val album6 = Album(albumId = "overitall", name = "Over It All", artist = artist2.id)
// saving to database
SongDatabase.invoke(applicationContext).library().save(artist)
SongDatabase.invoke(applicationContext).library().save(artist2)
SongDatabase.invoke(applicationContext).library().save(album1, album2, album3, album4, album5, album6)
Logging all Artists
val all = SongDatabase.invoke(applicationContext).library().getAll()
Log.d("debug", "All Artists $all ")
D/debug: All Artists [ArtistAndAlbums(artist=Artist(id=hillsongunited, name=Hillsong United), albums=[Album(albumId=empires, name=Empires, artist=hillsongunited), Album(albumId=wonder, name=Wonder, artist=hillsongunited), Album(albumId=people, name=People, artist=hillsongunited)]), ArtistAndAlbums(artist=Artist(id=planetshakers, name=Planet Shakers), albums=[Album(albumId=rain, name=Rain, artist=planetshakers), Album(albumId=itschristmas, name=Its Christmas, artist=planetshakers), Album(albumId=overitall, name=Over It All, artist=planetshakers)])]
Logging albums by a specific artist,
val hillsongAlbums = SongDatabase.invoke(applicationContext).library().getByArtistId(artist.id)
Log.d("debug", "Albums by artist ID: $hillsongAlbums ")
D/debug: Albums by artist ID: ArtistAndAlbums(artist=Artist(id=hillsongunited, name=Hillsong United), albums=[Album(albumId=empires, name=Empires, artist=hillsongunited), Album(albumId=wonder, name=Wonder, artist=hillsongunited), Album(albumId=people, name=People, artist=hillsongunited)])

- 24,861
- 16
- 87
- 111
-
1For `one-to-many` relationships you should rename `ArtistAndAlbums` with `ArtistWithAlbums`. – Sumit Shukla Mar 22 '21 at 04:35
-
@SumitShukla its just a naming convention, nothing to do with the naming actually. – All Іѕ Vаиітy Jul 14 '22 at 05:35
@ForeignKey
annotations are not used to define relations when getting data but to define relations when modifying data. To get relational data from a Room databse, Google recommends the @Relation
along with the @Embedded
annotation.
You can check out my answer here for more explanation if you're interested.

- 1,212
- 13
- 20