【问题标题】:(Spring boot) can Optional<> Class be like List<> Class?(Spring boot) Optional<> Class 可以像 List<> Class 吗?
【发布时间】:2018-05-04 09:46:30
【问题描述】:

我试图将 RoomEntity 类作为其通用参数放入列表中,但列表类变为红色(错误),它唯一建议的是将列表类更改为可选类。

public interface RoomRepository extends CrudRepository<RoomEntity, Long> {
    List<RoomEntity> findById(Long id);
}

RoomEntity 类

@Entity
@Table(name = "Room")
public class RoomEntity {

}

它们是一样的吗?

List<RoomEntity> findById(Long id); 
Optional<RoomEntity> findById(Long id);

【问题讨论】:

  • 不,它们不一样。 Optional 可以包含零个或单个元素。 List 可以包含零个、一个或多个元素。请发布确切的错误消息,但我想这是因为id 是 PK 并且您不能通过 PK 获得多个元素
  • 好吧,在不太了解 SpringBoot 以及“类变红”的情况下,ID 通常是唯一的,它们要么存在,要么不存在,您通常不能拥有多个。所以 Optional 似乎很合适。

标签: java list spring-boot optional


【解决方案1】:

Optional 和 List 是两个截然不同的概念。

CrudRepository findAllById 方法返回一个 Iterable。 findById 方法返回一个 Optional。

可迭代对象可用于逐个访问集合的元素,因此可与 List 类结合使用。

Optional 是一个容器对象,它可能包含也可能不包含非空值(零或一个元素)。这将有一个元素,如果有的话,不会像 List 那样有很多元素。

CrudRepository::findAllById 可以有多个 ID 发送给它,因此可以返回多个元素,这样做的方式是返回一个可用于一一选择每个返回结果的可迭代对象。 findById 方法只能发送一个 ID,因此如果存在则返回该元素(包装在 Optional 中),如果不存在则返回 Optional.none。

如果您正在寻找要返回的列表,因为您打算发送多个 ID,请使用 findAllById 方法。如果您只需要 ID 的特定元素,则使用 findById 方法,但是您必须先解开它返回的 Optional 对象,然后才能在流管道之外使用 Optional.get、Optional.isPresent 或使用在流管道中对其进行地图或平面地图调用。

【讨论】:

    【解决方案2】:

    Spring data JPA 会将查询结果适合您所需的容器

    您询问List&lt;&gt;,Spring 将初始化一个列表并将任何行数据添加到该列表并为您返回。因此它将:

    1. 如果未找到任何项目,则返回空列表
    2. 如果找到项目,则返回填充列表

    当您询问Optional&lt;&gt; 时,Spring 会明白您最多需要一行数据。它将在javax.persistence.Query 上解释为getSingleResult()。因此它将:

    1. 如果没有找到项目,则返回Optional.empty()

    2. 如果正好有一个匹配,则返回 Optional.of(result)

    3. 如果有多个匹配项则抛出异常(我记得的那个是NonUniqueResultException

    在您的情况下,您可以通过 id 找到。它在您的餐桌上是独一无二的,所以 Optional&lt;&gt; 应该适合您的目的。

    但请注意,您的List&lt;RoomEntity&gt; findById(Long id); 定义是正确的,它不会给您带来编译器错误(变为红色)。 List接口你导入了吗?

    【讨论】:

    • 谢谢伙计。现在更清楚了。是的,我已经导入了它。但我还是得到了答案。干杯!
    • 嗨,Manh,Spring data JPA will fit the query result to your desired container,你有参考资料吗?
    【解决方案3】:

    findById 方法应该通过它的 id 来查找单个实体。毕竟,每个实体的 id 都是唯一的。

    您可以尝试使用findAllById, 但我怀疑它会产生很大的不同。

    可选的意思是可能有也可能没有结果。 Optional 的isPresent 方法会表明这一点。

    【讨论】:

      【解决方案4】:

      根据定义,您的 findById 应始终返回 1 或 0 个实体(根据 documentation 用于 spring 数据方法命名),因为您的 id 是唯一键,并且您的存储库中不能有多个条目具有这样的关键价值。所以Optional 非常适合这种情况,因为它要么是empty(存储库中没有具有此类键的条目),要么是具有特定值的present(存储库中有条目)。如果你想通过一些非唯一键查询所有实体,比如说name 列,你可以将你的方法命名为findByName,返回值为Iterable&lt;Entity&gt;,因此在为你的存储库生成实现时,spring 会明白可以结果集中超过 1 个实体。

      方法findById在你扩展的接口中已经是predefined,所以无论如何你都不能改变它的返回类型。

      这也可能有用:https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.core-concepts

      【讨论】:

        猜你喜欢
        • 2011-09-29
        • 2016-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-31
        • 2023-03-19
        • 2014-12-22
        相关资源
        最近更新 更多