You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 00:55:34