PowerSyncException:调用get() 时,查询未返回任何行

移动开发 2026-07-10

我正在把PowerSync集成到一个Android应用。启动应用时,我得到如下错误:

PowerSyncException: get() called with query that returned no rows

错误。仅此而已,它没有指向具体的文件或方法。我猜这个错误会涉及我所有的 powerSyncDatabase.get() 方法。下面是我如何使用 get() 方法的一个示例:

fun selectGoalById(id: UUID): Flow<Goal> {
        return flow {
            try {
                val goal = dataSource.getDatabase().get(
                    sql = "SELECT * FROM goals WHERE id = ?",
                    parameters = listOf(id)
                ) { cursor ->
                    Goal(
                        id = UUID.fromString(cursor.getString("id")),
                        createdAt = cursor.getString("created_at"),
                        userId = UUID.fromString(cursor.getString("user_id")),
                        title = cursor.getString("title"),
                        priority = cursor.getString("priority").toInt()
                    )
                }
                emit(goal)
            } catch (e: Exception) {
            }
        }
    }

PowerSync数据库到现在确实应该是空的,那么我是否应该对查询返回结果采取不同的处理?

解决方案

文档指出,get 函数在“发生数据库错误或未找到结果”的情况下会抛出异常。所以看起来在给定的id下数据库中没有对应的Goal。

如果这是你的业务逻辑允许的,那么你应该把 get() 替换为 getOptional(),在未找到任何内容时它会返回 null,而不是抛出异常。

不过,值得怀疑的是你把结果包装在一个Flow中。Flow用于异步提供数据流。但你在Flow里只输出了一个单一的值。鉴于查询的“一次性”性质,在这里使用Flow似乎不太合适。若你确实希望在数据库有任何变化时得到通知,那么就需要重新执行查询。届时,Flow才合适,因为这个新结果也可以随后被输出到Flow中。

幸运的是,PowerSync已内置对这点的支持:

fun selectGoalById(id: UUID): Flow<Goal> = dataSource.getDatabase()
    .watch(
        sql = "SELECT * FROM goals WHERE id = ?",
        parameters = listOf(id)
    ) { cursor ->
        Goal(
            id = UUID.fromString(cursor.getString("id")),
            createdAt = cursor.getString("created_at"),
            userId = UUID.fromString(cursor.getString("user_id")),
            title = cursor.getString("title"),
            priority = cursor.getString("priority").toInt(),
        )
    }
    .map { it.single() }

函数 watch 返回一个包含所有结果的Flow(对于数据库的每一次变更,都会得到一个包含Goals的 List)。为了确保只返回一个单一的结果,随后会把这个Goals List映射成一个单独的Goal。这表示原本在没有找到任何Goal时应用崩溃的行为。如果你想改为返回 null,只需把 it.single() 替换为 it.firstOrNull(),并把函数的返回类型改为 Flow<Goal?>

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章