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

Room数据库插入1-N关系表数据不全问题排查求助

问题根因与修复方案

排查代码后共存在4处核心错误导致插入异常、遍历逻辑混乱:

1. DAO层方法声明错误

你的insertRoutePoints方法添加了@Transaction注解,但没有声明为suspend函数,在IO协程中调用时会触发Room的线程访问异常,执行中断后看起来像是逻辑回退到了forEach循环。
修复方案:给插入方法添加suspend修饰符:

@Dao 
interface RouteDao {
    @Insert(onConflict = IGNORE)
    suspend fun insertRoute(route: Route)

    @Query("SELECT * FROM routes_tbl")
    fun getAllRoutes(): List<Route>

    @Transaction
    @Insert
    suspend fun insertRoutePoints(points: List<PointOfInterest>) 
}

2. 列表插入逻辑错误

你使用listOfPoints.add(id, pointOfInterest)按下标插入元素,该方法第一个参数是列表的下标位置,不是业务上的id值。如果Firebase返回的point.key不是从0开始连续递增的数值,会直接抛出下标越界异常,同时导致列表size统计错误,触发多次插入。
修复方案:直接追加元素即可,不需要指定下标:

// 错误写法
listOfPoints.add(id, pointOfInterest)
// 正确写法
listOfPoints.add(pointOfInterest)

3. 遍历完成判断逻辑错误

你把列表长度判断、插入逻辑放在forEach循环内部,会导致每次新增元素都触发一次判断,若出现元素插入异常导致size统计不准,会多次触发插入操作,出现逻辑混乱。
修复方案:把插入逻辑移到forEach循环外部,等所有元素解析完成后统一插入:

private fun getRoutePoints(routeId: String) {
    val dbReference = FirebaseDatabase.getInstance().getReference("/routes/$routeId")
    val listOfPoints: MutableList<PointOfInterest> = mutableListOf()
    dbReference.child("pointsOfInterest").get().addOnSuccessListener { pointsArray ->
        val routeIdToInsert = routeId.toInt()
        // 遍历解析所有点位
        pointsArray.children.forEach { point ->
            val dataMap = point.value as Map<*, *>
            val id = point.key!!.toInt()
            val pointOfInterest = PointOfInterest(
                id = id,
                title = dataMap["title"].toString(),
                description = dataMap["description"].toString(),
                latitude = dataMap["latitude"].toString().toDouble(),
                longitude = dataMap["longitude"].toString().toDouble(),
                imageUrl = dataMap["imageUrl"].toString(),
                routeId = routeIdToInsert
            )
            listOfPoints.add(pointOfInterest)
        }
        // 遍历完成后统一插入
        CoroutineScope(Dispatchers.IO).launch {
            AppDatabase.getInstance(application).routeDao.insertRoutePoints(listOfPoints)
        }
    }
}

4. 外键约束未校验

你给points_tbl设置了关联routes_tbl的外键约束,插入兴趣点前必须确保对应id的Route数据已经提前插入到Room数据库中,否则外键约束会直接拒绝兴趣点的插入请求,导致数据插入不全。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 10:57:08