Spring Data JPA:使用可选参数调用存储库方法的有效方式
Spring Data JPA : Efficient Way to Invoke Repository Methods with Optional Parameters
我有下面的 Java 11
方法,该方法由控制器调用,其中 ID
是必需参数,status
、version
是可选参数。我不得不编写多个 repository
方法来根据这些参数获取记录。我想知道是否有一种 better/effiecient 方法可以在没有 if/else 阶梯的情况下重构此方法?
@Override
@Transactional(transactionManager = "customTransactionManager")
public Optional<String> getInformation(UUID id, Status status, Long version) {
try {
Preconditions.checkNotNull(id, ID_MUST_BE_NOT_NULL_MSG);
if (status != null && version != null) {
return repository.findByIdAndVersionAndStatus(id, version, status);
} else if (status != null) {
return repository.findFirstByIdAndStatus(id, status);
} else if (version != null) {
return repository.findFirstByIdAndVersion(id, version);
} else {
return repository.findFirstByIdOrderByIdDesc(id);
}
} catch (Exception e) {
log.error(e);
throw new CustomException(MessageFormat.format(PUBLIC_ERROR_MESSAGE, id));
}
}
你可以使用 Specifications:
private Specification<YourEntity> toSpecification(UUID id, Status status, Long version) {
return (root, query, builder) -> {
Set<Predicate> predicates = new HashSet<>();
predicates.add(builder.equal(root.get("id"), id));
if (status != null) predicates.add(builder.equal(root.get("status"), status));
if (version != null) predicates.add(builder.equal(root.get("version"), version));
return builder.and(predicates.toArray(Predicate[]::new));
};
}
如果您让存储库扩展 JpaSpecificationExecutor
,您可以像这样使用构建规范对象:
Specification<YourEntity> specification = toSpecification(id, status, version);
Optional<YourEntity> result = repository.findOne(specification);
当使用 Hibernate Metamodel Generator 时,您也可以写 builder.equal(YourEntity_.id, id)
而不是 builder.equal(root.get("id"), id)
。
除了被接受的答案之外,我发现 Query By Examples 更加直观和简单。
https://www.baeldung.com/spring-data-query-by-example 将是一个好的开始。
它基本上是根据您的 jpa 实体中的非空字段创建查询。
我有下面的 Java 11
方法,该方法由控制器调用,其中 ID
是必需参数,status
、version
是可选参数。我不得不编写多个 repository
方法来根据这些参数获取记录。我想知道是否有一种 better/effiecient 方法可以在没有 if/else 阶梯的情况下重构此方法?
@Override
@Transactional(transactionManager = "customTransactionManager")
public Optional<String> getInformation(UUID id, Status status, Long version) {
try {
Preconditions.checkNotNull(id, ID_MUST_BE_NOT_NULL_MSG);
if (status != null && version != null) {
return repository.findByIdAndVersionAndStatus(id, version, status);
} else if (status != null) {
return repository.findFirstByIdAndStatus(id, status);
} else if (version != null) {
return repository.findFirstByIdAndVersion(id, version);
} else {
return repository.findFirstByIdOrderByIdDesc(id);
}
} catch (Exception e) {
log.error(e);
throw new CustomException(MessageFormat.format(PUBLIC_ERROR_MESSAGE, id));
}
}
你可以使用 Specifications:
private Specification<YourEntity> toSpecification(UUID id, Status status, Long version) {
return (root, query, builder) -> {
Set<Predicate> predicates = new HashSet<>();
predicates.add(builder.equal(root.get("id"), id));
if (status != null) predicates.add(builder.equal(root.get("status"), status));
if (version != null) predicates.add(builder.equal(root.get("version"), version));
return builder.and(predicates.toArray(Predicate[]::new));
};
}
如果您让存储库扩展 JpaSpecificationExecutor
,您可以像这样使用构建规范对象:
Specification<YourEntity> specification = toSpecification(id, status, version);
Optional<YourEntity> result = repository.findOne(specification);
当使用 Hibernate Metamodel Generator 时,您也可以写 builder.equal(YourEntity_.id, id)
而不是 builder.equal(root.get("id"), id)
。
除了被接受的答案之外,我发现 Query By Examples 更加直观和简单。
https://www.baeldung.com/spring-data-query-by-example 将是一个好的开始。
它基本上是根据您的 jpa 实体中的非空字段创建查询。