我正在编写一个代码生成工具,使用 Spring Data JPA 为 Spring Boot 应用程序生成后端接线代码,令我有点恼火的是
CrudRepository
中的方法返回 Iterable
而不是 List
,如 Iterable
没有提供足够的功能,但 List
可以,所以我正在寻找将 Iterable
转换为 List
的最佳方法。
我看到这篇文章将
Iterable
更改为Collection
,我想知道,与其使用像Guava这样的库或实现我自己的函数来进行转换,为什么不将其转换为List
?这样做是不是有什么我不知道的错误?
编辑: 我问这个问题是因为它是一个代码生成工具,让它生成引入对第三方库的依赖关系的代码是不合理的,并且编写我自己的函数来进行转换也不是很合理,因为它必须位于某个地方,而我不想在生成的代码中包含它。一个简单的演员阵容就可以了,虽然有点难看,但只是想知道我是否遗漏了一些东西?
不,我觉得不行。
虽然
List
保证是 Iterable
,但 Iterable
可能不是 List
。这意味着如果您确实将 Iterable
转换为 List
,它可能会在运行时失败。即使它有效,也不能保证它在未来会继续工作,因为它可能会在新版本的 Spring Data JPA 中发生变化,而不会破坏接口的契约。
您应该声明自己的返回
List
的查询方法,而不是使用强制转换。
您也可以使用
Streamable.of(iterable).toList()
进行转换。 这个答案还包含一些背景知识,为什么选择Iterable
作为这些方法的返回类型。
您的接口仍然可以扩展CrudRepository,您只需添加一个返回列表的新方法 findAll 即可。就像下面的例子:
@Repository
public interface DataRepository extends CrudRepository<Data, Long> {
@Override
List<Data> findAll();
}
如果您有一个“抽象”存储库要由所有存储库扩展,您也可以添加此方法,这样它将对您的所有存储库都有效。就像下面的例子:
@NoRepositoryBean
public interface GenericRepository<T> extends CrudRepository<T, Long> {
@Override
List<T> findAll();
}
从 Spring Data 3 开始,还有另一个选项:
ListCrudRepository
。
这篇博文介绍了为什么
CrudRepository
选择 Iterable
而不是 List
。
https://spring.io/blog/2022/02/22/announcing-listcrudrepository-friends-for-spring-data-3-0
嗨,我知道我来晚了,但如果你想将 Iterable 转换为 Collection,你可以这样做。
private <T> Collection<T> map(final Iterable<T> iterable) {
return StreamSupport.stream(iterable.spliterator(), false)
.collect(Collectors.toCollection(HashSet::new));
}
之后du可以通过.stream().toList()得到一个List;关于收藏。希望有帮助
简单地说,您可以使存储库扩展 JpaRepository 而不是 CrudRepository。这将完美地发挥作用。这里 findAll 返回一个 List 而不是 Iterable。
我不知道这是否可以帮助将来的任何人,但是在您的 @Repository 界面中,您可以扩展 ListCrudRepository 而不是 CrudRepository
public interface StudentRepository extends ListCrudRepository<student, Integer> {
}
然后在你的控制器中你可以获得一个列表:
@GetMapping("")
List<student> findAll() {
return studentRepository.findAll();
}