如何使用Spring Data JPA方法在Kotlin的try-with-resources块中返回Stream?

所以我想使用Kotlin创建一个使用Spring Data JPA项目的Spring Boot ,并让我说我有一个Person实体。 让我们这样说吧:

 @Entity public class Person { private @GeneratedValue @Id Long id; private String name; @OneToMany private List<Person> friends; … } 

我将创建以下接口,以便能够使用Try-with-ResourcesStream<Person>

 public interface PersonRepository extends Repository<Person, Long> { @Query("select p from Person p") Stream<Person> findAllStream(); } 

所以通常在我的服务,我会这样做:

 @Service class MyService { @Autowired PersonRepository repository; List<String> foo() { try(Stream<Person> stream = repository.findAllStream()) { return stream.flatMap(p -> p.getFriends().stream()) .map(f -> f.getName()) .collect(Collectors.toList()); } } } 

现在,如果你想在Kotlin(IntelliJ转换器不生成有效的代码)中做到这一点。 我想你通常会这样做:

 class MyService @Autowired constructor(val personRepository: PersonRepository) { fun foo() { val list = personRepository.findAllStream() .use {{p -> p.friends.stream()}.map {f -> f.name}} } } 

只有你不能这样做,因为没有#use方法在流,你不能从List调用#stream() 。 那么有没有办法做到这一点?

那么,Java 8支持在Kotlin中还没有完成。 所以你可以像这样宣布在你身边使用

 inline fun <A : AutoCloseable, R> A.use(block: (A) -> R): R { try { return block(this) } finally { close() } } 

另一种方法是直接在Stream上声明

 inline fun <T, R> Stream<T>.use(block: (Stream<T>) -> R): R { try { return block(this) } finally { close() } } 

UPD

如果您是Kotlin的新手,则必须注意,扩展名是静态解析的:

扩展实际上并不修改它们扩展的类。 通过定义扩展,不要将新成员插入到类中,而只需使用此类的实例上的点符号来调用新函数。

查看更多http://kotlinlang.org/docs/reference/extensions.html#extensions-are-resolved-statically