这是我们的代码

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

}

可能是什么问题呢?

最佳答案

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

是原因。

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

执行的顺序是某种方式:
  • specRepo.findByIdentificationType(idType)
  • orElse无法执行,因为它的参数尚未评估
  • specRepo.findById(idType)
  • .orElseThrow(() -> new ResourceNotFoundException("..."))
  • 3和4的结果成为对象o
  • orElse(o)

  • 而不是使用orElse,应该选择orElseGet
    return specRepo.findByIdentificationType(idType)
                .orElseGet(() -> specRepo.findById(idType)
                    .orElseThrow(() -> new ResourceNotFoundException("...")));
    

    仅在需要时才调用它。

    这里有两种情况:
  • specRepo返回一个非空的Optional。
  • specRepo返回空对象。

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

    编辑:

    尽管此答案可以诊断问题并描述这种行为的原因,但是@Abinash Ghosh答案提供了最简单,最完美的imo解决方案。

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

    09-11 20:02