这是我们的代码
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
。问题是,即使ResourceNotFoundException
或op1
不为空,它也会抛出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("..."))
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
答案提供了该问题的最简单和最佳的解决方案。
通常,避免使用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);
}