这是我们的代码
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
。表只有两列id
和identificationType
。问题是,即使op1
或op2
不为空,它也会抛出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方法来进行准备,以备不时之需
你的处决顺序是:
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
返回一个非空的OptionalspecRepo
返回空对象
在场景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);
}