如何使用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-Resources
和Stream<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