Model a Room one-to-many Playlist-to-Song relationship

Tests Room relational modeling. Strong answer: Song foreign key, @Embedded Playlist with @Relation to List<Song>, DAO wrapped in @Transaction. Red flag: embedding songs in Playlist or skipping @Transaction, which causes N+1 queries.
What's really being asked
This tests whether you understand how Room abstracts SQL relationships into object graphs without breaking relational normalization. The interviewer cares that you know the difference between an entity and a POJO used for projection, that you understand foreign keys for referential integrity, and that you know Room can automatically fetch related objects in a single transaction rather than forcing you to write manual joins.
The full answer
A good answer hits four things in order. First, define two separate entities: Playlist with a primary key, and Song with its own primary key plus a foreign key column referencing playlistId. Second, create a dedicated data class that is not an entity, such as PlaylistWithSongs, annotated with @Embedded for the Playlist field and @Relation on the List<Song> field mapping parentColumn to the Playlist primary key and entityColumn to the Song foreign key. Third, in the DAO, write a method that returns PlaylistWithSongs and annotate it with @Transaction so Room runs two queries in a single transaction and assembles the object graph for you without an N plus one problem. Fourth, mention adding an index on the Song foreign key column to avoid full table scans during the relation query.
The mistakes people make
The biggest red flag is suggesting you store a list of Song objects directly inside the Playlist entity using @Embedded or a type converter, which collapses the relationship into one table and violates first normal form. Another red flag is proposing manual nested queries where you fetch all playlists then loop to query songs individually, which creates an N plus one performance disaster. A subtler mistake is forgetting @Transaction, which can leave you with partial data if the database changes between the two internal queries Room runs.
What usually comes next
The interviewer might ask how you would model a many-to-many relationship between playlists and songs, which requires a join entity. They might ask what happens if you omit the index on the foreign key, which leads to slower relation lookups on large datasets. They could also ask how you would observe changes, prompting you to return Flow<List<PlaylistWithSongs>> so Room automatically emits updates.
A concrete example
Imagine a playlist table with columns id and name, and a song table with columns songId, title, and playlistId. You define PlaylistWithSongs with @Embedded val playlist: Playlist and @Relation parentColumn set to id and entityColumn set to playlistId on val songs: List<Song>. Your DAO has @Transaction @Query SELECT * FROM playlist WHERE id = :playlistId fun getPlaylistWithSongs(playlistId: Long): PlaylistWithSongs. Room executes a select on playlist, then a select on song where playlistId matches, and maps both into the result object in one shot.
Interview question
In Room, why should a DAO method returning a PlaylistWithSongs relation POJO be annotated with @Transaction?
- a.To ensure the two internal SELECT queries run atomically so concurrent writes cannot leave the result partially inconsistentCorrect
- b.To prevent an N+1 query problem by combining the playlist and song lookups into a single SQL JOIN statement
- c.To allow the Playlist entity to embed the List<Song> directly while maintaining normalized storage
- d.To create a foreign key constraint automatically between the Song and Playlist tables
Why? this is the answer
@Transaction guarantees that the two separate SELECT queries Room runs under the hood execute in a single atomic transaction, preventing concurrent writes from yielding an incomplete object graph. It does not merge those queries into one JOIN statement; Room still fetches the parent and child rows separately.
Just read this? Test yourself on what you have been reading.
Read the original → developer.android.com
You just looked this up. Could you explain it out loud?
That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.
We are hiring for this. Open roles that interview on android — each one lists the topics its interview covers.
See open roles