JPA findBy方法总是转到orElseThrow



这是我们的代码

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。问题是,即使op1op2不为空,它也会抛出ResourceNotFoundException。现在,如果我像这个一样更改我的退货

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方法来进行准备,以备不时之需

你的处决顺序是:

  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)添加到存储库中。

@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);
}

最新更新