【问题标题】:Unable to iterate over stream inside use{} block无法在 use{} 块内迭代流
【发布时间】:2023-03-19 20:57:01
【问题描述】:

我只想打印存储在数据库中的每个用户的名称。

我正在使用这个存储库:

@Repository
interface User: JpaSpecificationExecutor<User>, PagingAndSortingRepository<User, Long> {

    @Query("from User")
    fun findAllUsers(): Stream<User>
}

在此服务内:

@Service
class MyService(val user: User) {
    private val log = LoggerFactory.getLogger(javaClass)

    @Transactional(readOnly = true)
    fun printNames() {
        log.info("here")
        user.findAllUsers().use { users ->
            users.map { it.firstName }
        }
    }
}

它只在控制台中打印 here,但没有名称。

似乎 map() 自动关闭了流,但我不知道为什么以及如何解决它。当我放入 use{} 块仅 log.info(users.count()) 时,它会打印存储在数据库中的用户数。所以有一个用户我可以打印。

我的问题是,如何打印给定流中的所有名称?

【问题讨论】:

  • 您将 Stream 与 kotlin 一起使用是否有原因?
  • 除了懒惰的map 什么都不做,注意这里没有与用户的打印或日志语句,你希望它们如何打印?
  • 这只是一个例子,因为我需要将用户对象传递给另一个发送到 Kafka 的函数

标签: spring kotlin spring-data


【解决方案1】:

Kotlin 的 use 函数只是执行某些代码(您的闭包函数)然后在完成后在接收器(在本例中为 Stream)上调用 close 的一种快捷方式。

你所谓的users实际上是你的存储库返回的Stream&lt;User&gt;,所以基本上你的代码只是调用users.map {...}。现在,map 运算符是一个中间运算符,由于 Java 流是惰性的,因此它们实际上不会做任何事情,直到您调用终端运算符(例如 .collect.forEach)。

假设您要打印用户,请尝试:

user.findAllUsers().use {
    it.forEach { println(it.firstName) }
}

完整的工作示例(没有 Spring 数据):

import java.util.stream.Stream

// simulate a repository
fun findAllUsers() = Stream.of("First", "Second", "Third")

fun printNames() {
    findAllUsers().use {
        it.forEach(::println)
    }
}

fun main() {
    printNames()
}

打印:

First
Second
Third

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-23
    • 1970-01-01
    • 2010-11-04
    • 2015-08-25
    • 1970-01-01
    • 2011-11-10
    • 2019-03-26
    相关资源
    最近更新 更多