我正在学习被动型。在MVC项目中,我有一个服务方法(控制器具有相同的签名(,如下所示:
@Override
public Map<Long, Question> getQuestions() {
List<Question> questions = questionRepo.findAllByType(Type.A);
return questions.stream()
.collect(Collectors.toMap(q -> q.getId(), q -> q));
}
导致类似的情况:
{
1: {id: 1, ...}
2: {id: 2, ...}
...
}
现在,切换到反应式和kotlin协同程序。以被动的方式实现这一点的正确方法是什么?
这是存储库的签名:
interface QuestionRepository : CoroutineCrudRepository<Question, Long> {
@Query("select * from Question q where type = :type")
fun findAllByType(type: Type): Flow<Question>
}
方法
到目前为止,我认为使用Mono<Map<Long,Question>>
似乎没有任何意义,因为它需要阻塞来构建内部映射。
Flow<Map<Long,Question>>
也没有意义,因为我们没有填充多个映射。
所以我现在最好的方法是不使用Map
。。。
override fun getQuestions(): Flow<Question> {
return questionRepo.findAllByType(Type.A)
}
但这需要更改前端代码(现在需要将列表转换为映射(。
我还想到
override fun getQuestions(): Flow<Pair<Long?,Question>> {
return questionRepo.findAllByType(Type.A).map { it.id to it }
}
但这也需要前端进行更改,因为输出看起来像
[{"first":1,"second":{"id":1, ...}]
还有其他更好的方法吗?你将如何实施它?
更新
添加了存储库。
假设Flow一次发射一个元素,您想将其放入客户端代码中的单个Map中,那么您可以将它们收集到这样的MutableMap中并返回它。
suspend fun getQuestions(): Map<Long, Question> {
val map = mutableMapOf<Long, Question>()
questionRepo.findAllByType(Type.A)
.collect {
map[it.id] = it
}
return map
}
如果您的下游客户端代码不期望挂起函数,我想您需要将其封装在runBlocking
中,并且下游代码可能已经在处理这是一个长时间运行的函数调用这一事实。
override fun getQuestions(): Map<Long, Question> = runBlocking {
val map = mutableMapOf<Long, Question>()
questionRepo.findAllByType(Type.A)
.collect {
map[it.id] = it
}
map
}