无法迭代 use{} 块内的流

Unable to iterate over stream inside use{} block

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

我正在使用这个存储库:

@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 }
        }
    }
}

它在控制台中只打印这里,但没有名字。

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

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

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

你调用的 users 实际上是你的存储库返回的 Stream<User>,所以基本上你的代码只是调用 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