JPA findBy 方法总是转到 orElseThrow
JPA findBy method always goes to 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
。 Table 只有两列 id
和 identificationType
。问题是即使 op1
或 op2
不为空,它也会抛出 ResourceNotFoundException
。现在,如果我像这样更改我的 return
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
returns 非空可选。
specRepo
returns 空对象。
在场景 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);
}
这是我们的代码
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
。 Table 只有两列 id
和 identificationType
。问题是即使 op1
或 op2
不为空,它也会抛出 ResourceNotFoundException
。现在,如果我像这样更改我的 return
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
returns 非空可选。specRepo
returns 空对象。
在场景 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);
}