JPA findBy方法始终转到orElseThrow

问题描述 投票:6回答:2

这是我们的代码

private IdentificationMaster validateIdentificationType(String idType) {
    if(!StringUtils.isNotBlank(idType))
        throw new IllegalArgumentException("Invalid idType");

    Optional<IdentificationMaster> op1 = specRepo.findById(idType); //testing purpose

    Optional<IdentificationMaster> op2 = specRepo.findByIdentificationType(idType); //testing purpose

    return specRepo.findById(idType)
            .orElse(specRepo.findByIdentificationType(idType)
                    .orElseThrow(() -> new ResourceNotFoundException("Id Type Not Found " + idType)));
}

对于idType,我们期望两个值可以是主键ID或其对应的identificationType。表只有两列ididentificationType。问题是,即使ResourceNotFoundExceptionop1不为空,它也会抛出op2。现在,如果我这样更改退货信息

return specRepo.findByIdentificationType(idType)
            .orElse(specRepo.findById(idType)
                .orElseThrow(() -> new ResourceNotFoundException("Id Type Not Found " + idType)));

再次引发相同的异常!

存储库

@Repository
public interface IdentificationSpecRepository extends CrudRepository<IdentificationMaster, String>{

    Optional<IdentificationMaster> findByIdentificationType(String identificationType);
}

实体

@Entity
@Table(name = "IDENTIFICATION_MASTER")
public class IdentificationMaster {

    @Id
    @Column(name = "ID")
    private String id;


    @Column(name = "IDENTIFICATION_TYPE", unique = true)
    private String identificationType;

    // getters and setters

}

可能是什么问题?

java spring-boot spring-data-jpa optional findby
2个回答
5
投票
return specRepo.findByIdentificationType(idType)
            .orElse(specRepo.findById(idType)
                .orElseThrow(() -> new ResourceNotFoundException("...")));

是原因。

Java非常渴望执行,并且总是调用orElse方法来准备以防万一。

执行顺序是某种方式:

  1. specRepo.findByIdentificationType(idType)
  2. [orElse无法执行,因为其参数尚未评估]
  3. specRepo.findById(idType)
  4. .orElseThrow(() -> new ResourceNotFoundException("..."))
  5. [3和4的结果成为对象o
  6. orElse(o)

而不是使用orElse,应该更喜欢orElseGet

return specRepo.findByIdentificationType(idType)
            .orElseGet(() -> specRepo.findById(idType)
                .orElseThrow(() -> new ResourceNotFoundException("...")));

仅在需要时才会调用。

我们在这里有两种情况:

  1. specRepo返回非空的Optional。
  2. [specRepo返回空对象。

在场景1中,idType是有效的identificationType,因此不是id,因此findById将引发异常。在方案2中,idType不是有效的identificationType,如果它是合法的id,则该方法应导致引发异常。

编辑:

虽然此答案诊断了问题并描述了这种行为的原因,但@Abinash Ghosh答案提供了该问题的最简单和最佳的解决方案。

通常,避免使用orElse。在这种情况下,请将findByIdentificationTypeOrId(String it, String id)添加到您的存储库中。


3
投票

@ xenteros是正确的,这就是问题所在。您可以使用findByIdentificationTypeOrId在一个查询中获取数据

return specRepo.findByIdentifcationTypeOrId(idType, idType)
                .orElseThrow(() -> new ResourceNotFoundException("...")));

和类似仓库

@Repository
public interface IdentificationSpecRepository extends CrudRepository<IdentificationMaster, String>{

    Optional<IdentificationMaster> findByIdentificationTypeOrId(String identificationType, String id);
}
© www.soinside.com 2019 - 2024. All rights reserved.