Android Room:查询播放列表及按位置排序的关联歌曲异常问题
问题分析与解决方案
核心问题1:默认查询未按position排序
Room的@Relation注解默认会按关联实体(这里是Song)的主键排序,不会自动使用交叉表的position字段。要实现按播放列表内的歌曲位置排序,只需在@Relation中指定排序规则即可。
核心问题2:自定义JOIN查询返回歌曲列表为空
自定义JOIN会返回扁平的结果集(每行包含播放列表、交叉表、歌曲的所有字段),但Room的@Embedded+@Relation机制依赖两次查询(先查播放列表,再批量查每个播放列表的关联歌曲)来构建嵌套的List<Song>结构。扁平结果集无法被Room自动映射为嵌套列表,因此歌曲列表为空。
修正步骤
1. 先修复交叉表的拼写错误
你的PlaylistSongCrossRef实体中,外键引用的Playlst::class是拼写错误,应改为Playlist::class:
@Entity( primaryKeys = ["playlistId", "songId"], foreignKeys = [ ForeignKey( entity = Playlist::class, // 修正拼写错误 parentColumns = ["id"], childColumns = ["playlistId"] ), ForeignKey( entity = Song::class, parentColumns = ["id"], childColumns = ["songId"] ) ] ) data class PlaylistSongCrossRef( val playlistId: Long, val songId: Long, val position: Int )
2. 在@Relation中添加排序规则
修改PlaylistWithSongs的@Relation注解,通过sortOrder指定按交叉表的position升序排序:
data class PlaylistWithSongs( @Embedded val playlist: Playlist, @Relation( parentColumn = "id", entityColumn = "id", associateBy = Junction( value = PlaylistSongCrossRef::class, parentColumn = "playlistId", entityColumn = "songId" ), sortOrder = "PlaylistSongCrossRef.position ASC" // 添加排序规则 ) val songs: List<Song> )
3. 使用原有查询方法即可
不需要自定义JOIN查询,直接用最初的查询方法就能返回按位置排序的结果:
@Query("SELECT * FROM playlist") fun loadAllWithSongs(): Flow<List<PlaylistWithSongs>>
内容的提问来源于stack exchange,提问作者metrik
相关产品推荐
相关产品推荐

