Spring-Data JPA CrudRepository returns 可迭代,可以将其转换为 List 吗?

Spring-Data JPA CrudRepository returns Iterable, is it OK to cast this to List?

我正在编写代码生成工具,使用 Spring-Data-Jpa 为 Spring-boot 应用程序生成后端连接代码,CrudRepository return Iterable 而不是 List,因为 iterable 没有提供足够的功能,但 List 可以,所以我正在寻找将 iterable 转换为列表的最佳方法。

我看到 this post 将可迭代对象更改为集合,我想知道,与其使用像 Guava 这样的库或实现我自己的函数来进行转换,为什么不直接将其转换为 List?这样做有什么我不知道的错误吗?

编辑: 我问是因为因为它是一个代码生成工具,所以让它生成引入对 3rd 方库的依赖的代码是不合理的,并且编写我自己的函数来进行转换也不是很合理,因为它必须存在于某个地方而且我宁愿在生成的代码中没有它。一个简单的转换就可以了,如果有点难看,但只是想知道我是否遗漏了什么?

不,我觉得不行。

虽然 List 一定是 Iterable,但 Iterable 不一定是 List。这意味着如果您确实将 Iterable 转换为 List,它可能会在运行时失败。即使它可以工作,也不能保证它在未来会继续工作,因为它可能会在 Spring Data JPA 的新版本中发生变化,而不会破坏接口的约定。

您应该声明自己的查询方法,而不是使用强制转换 return List.

或者您可以使用 Streamable.of(iterable).toList() 进行转换。 This answer 还包含一些背景,为什么选择 Iterable 作为这些方法的 return 类型。

您提到了 [spring-data-jpa] 所以我猜您使用的是 JPA。在这种情况下,使用 JpaRepository 而不是 CrudRepository,方法 return List 就像您想要的那样。

您的接口仍然可以扩展 CrudRepository,您只需添加一个返回列表的新方法 findAll。像下面的例子:

@Repository
public interface DataRepository extends CrudRepository<Data, Long> {

    @Override
    List<Data> findAll();

}

如果你有一个 "abstract" 仓库要被你所有的仓库扩展,你也可以添加这个方法,所以它会影响你的所有仓库。像下面的例子:

@NoRepositoryBean
public interface GenericRepository<T> extends CrudRepository<T, Long> {

    @Override
    List<T> findAll();

}

从Spring数据3开始还有一个选项:ListCrudRepository.

此博客 post 介绍了 CrudRepository 选择 Iterable 而不是 List 的原因。

https://spring.io/blog/2022/02/22/announcing-listcrudrepository-friends-for-spring-data-3-0