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

如何在Room数据库中处理API返回的一对多嵌套实体的增查

处理Room中的嵌套一对多关系DTO

一、批量保存DTO数据到Room

要避免嵌套循环,可借助Kotlin集合操作(flatMap)提取所有层级的实体,再通过Room事务批量插入,保证操作原子性:

1. 优化saveFetchResult实现

saveFetchResult = { dtos ->
    // 提取各层级实体,用flatMap展开嵌套列表
    val boards = dtos.map { it.toEntityModel() }
    val boardChildren = dtos.flatMap { it.boardChildren.map { child -> child.toEntityModel() } }
    val boardElements = dtos.flatMap { it.boardChildren.flatMap { child -> child.boardElements.map { elem -> elem.toEntityModel() } } }
    val hyperlinks = dtos.flatMap { 
        it.boardChildren.flatMap { child -> 
            child.boardElements.flatMap { elem -> 
                elem.hyperlinks.map { link -> link.toEntityModel() } 
            } 
        } 
    }

    // 调用Dao的事务方法完成批量插入
    boardDao.insertAllData(boards, boardChildren, boardElements, hyperlinks)
}

2. 给Dao添加事务与批量插入方法

@Dao
interface BoardDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertAllBoards(boards: List<BoardEntity>)

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertAllBoardChildren(children: List<BoardChildEntity>)

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertAllBoardElements(elements: List<BoardElementEntity>)

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertAllHyperlinks(hyperlinks: List<BoardElementHyperlinkEntity>)

    // 用@Transaction确保所有插入操作原子性
    @Transaction
    suspend fun insertAllData(
        boards: List<BoardEntity>,
        children: List<BoardChildEntity>,
        elements: List<BoardElementEntity>,
        hyperlinks: List<BoardElementHyperlinkEntity>
    ) {
        insertAllBoards(boards)
        insertAllBoardChildren(children)
        insertAllBoardElements(elements)
        insertAllHyperlinks(hyperlinks)
    }
}

二、查询包含完整子列表的BoardEntity

通过Room的@Relation注解定义关联数据类,直接查询出包含所有子层级的完整数据结构:

1. 定义关联数据类

// 包含BoardElement及其关联的Hyperlinks
data class BoardElementWithHyperlinks(
    @Embedded val element: BoardElementEntity,
    @Relation(
        parentColumn = "id",
        entityColumn = "boardElementId"
    )
    val hyperlinks: List<BoardElementHyperlinkEntity>
)

// 包含BoardChild及其关联的Elements
data class BoardChildWithElements(
    @Embedded val child: BoardChildEntity,
    @Relation(
        parentColumn = "id",
        entityColumn = "boardChildId",
        entity = BoardElementEntity::class
    )
    val elements: List<BoardElementWithHyperlinks>
)

// 最终的完整Board结构:包含所有子层级
data class BoardWithChildren(
    @Embedded val board: BoardEntity,
    @Relation(
        parentColumn = "id",
        entityColumn = "boardId",
        entity = BoardChildEntity::class
    )
    val children: List<BoardChildWithElements>
)

2. 在Dao中添加关联查询方法

@Dao
interface BoardDao {
    // ... 其他方法 ...

    @Transaction
    @Query("SELECT * FROM BoardEntity")
    suspend fun getAllBoardsWithChildren(): List<BoardWithChildren>
}

3. 在networkBoundResource的query中使用

query = {
    boardDao.getAllBoardsWithChildren()
}

这样就能直接获取包含所有嵌套子实体的BoardWithChildren列表,无需手动拼接查询结果。


内容的提问来源于stack exchange,提问作者psclkhoury

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 15:45:52