Reputation: 3848
I have the below Java 11
method which is invoked by the controller where ID
is the required param and status
,version
are optional params. I had to write multiple repository
methods to fetch the record based on those params. Am wondering is there a better/effiecient way to refactor this method with out the if/else ladder?
@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));
}
}
Upvotes: 2
Views: 292
Reputation: 116
In addition to the accepted answer, I find Query By Examples much more intuitive and simple.
https://www.baeldung.com/spring-data-query-by-example would be a good start.
It basically creates a query based on non-null fields from your jpa entity.
Upvotes: 0
Reputation: 3178
You could use Specifications for that:
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));
};
}
If you let your repository extend JpaSpecificationExecutor
you can use the build specification object like so:
Specification<YourEntity> specification = toSpecification(id, status, version);
Optional<YourEntity> result = repository.findOne(specification);
When using Hibernate Metamodel Generator you can also write builder.equal(YourEntity_.id, id)
instead of builder.equal(root.get("id"), id)
.
Upvotes: 3