如何在 Kotlin 的 try-with-resources 块中使用 Spring Data JPA 方法返回 Stream?
How to use Spring Data JPA methods returning a Stream in a try-with-resources block in Kotlin?
所以我想使用 Kotlin
创建一个 Spring Boot
和 Spring Data JPA
项目,假设我有一个 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 Kotlin 对 8 的支持尚未完成。所以你可以像这样在你这边声明使用
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 的新手,您必须注意扩展是静态解析的:
Extensions do not actually modify classes they extend. By defining an extension, you do not insert new members into a class, but merely make new functions callable with the dot-notation on instances of this class.
查看更多http://kotlinlang.org/docs/reference/extensions.html#extensions-are-resolved-statically
所以我想使用 Kotlin
创建一个 Spring Boot
和 Spring Data JPA
项目,假设我有一个 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 Kotlin 对 8 的支持尚未完成。所以你可以像这样在你这边声明使用
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 的新手,您必须注意扩展是静态解析的:
Extensions do not actually modify classes they extend. By defining an extension, you do not insert new members into a class, but merely make new functions callable with the dot-notation on instances of this class.
查看更多http://kotlinlang.org/docs/reference/extensions.html#extensions-are-resolved-statically