I just want to print name of every user stored in database.
I am using this repository:
@Repository
interface User: JpaSpecificationExecutor<User>, PagingAndSortingRepository<User, Long> {
@Query("from User")
fun findAllUsers(): Stream<User>
}
inside this Service:
@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 }
}
}
}
and it prints only here in console, but no name.
It seems like map() automatically closed the stream but I don`t know why and how to workaround it. When I put inside of use{} block only log.info(users.count()) it prints number of users stored in database. So there is a user I can print.
My question is, how can I print all names from the given stream?
Kotlin's use
function is just a short-hand way of executing some code (your closure function) and then call close
on the receiver (in this case the Stream
) once done.
What you called users
is actually the Stream<User>
returned by your repository, so basically your code is just calling users.map {...}
. Now, the map
operator is an intermediate operator, and since Java streams are lazy, they won't actually do anything until you call a terminal operator (such as .collect
or .forEach
).
Assuming you want to print the user, try with:
user.findAllUsers().use {
it.forEach { println(it.firstName) }
}
Full working example (without Spring data):
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()
}
Prints:
First
Second
Third