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
相关产品推荐
相关产品推荐

