Reputation: 2546
I have this mission repository:
@Repository
interface MissionRepository: CrudRepository<MissionEntity, String>, JpaSpecificationExecutor<MissionEntity>
In my mission service class, I would like to fetch all missions that have their countryId
parts of the given argument Set
:
fun findAllByCountryIdIn(countryIds: Set<String>): List<MissionEntity> =
missionRepository.findAll(where(countryIdIn(countryIds)))
}
Where countryIdIn
(using in
predicate) comes from:
class MissionSpecifications {
companion object {
fun countryIdIn(countryIds: Set<String>): Specification<MissionEntity> =
Specification { root, _, _ -> root.get<String>("countryId").`in`(countryIds) }
}
}
But when the Set
is empty I got a predictable sql error. Is there a way to activate the where clause only when the given set is not empty? Without a if/else check? Maybe my specification syntax could be improve to avoid this sql error?
Upvotes: 2
Views: 3074
Reputation: 2546
An other solution would be:
@Repository
interface MissionRepository: JpaRepository<MissionEntity, String> {
fun findByCountryIdIn(countryIds: Set<String>, pageable: Pageable): Page<MissionEntity>
}
where you can add pagination.
Upvotes: 0
Reputation: 23312
I would rather return earlier instead. So just don't add a where if you do not require it in the first place. You can do that in several ways, e.g. using takeIf
, a simple if
, a when
, etc.
Just listing some samples:
fun findAllByCountryIdIn(countryIds: Set<String>) = countryIds.takeIf { it.isNotEmpty() }
?.let { missionRepository.findAll(where(countryIdIn(it))) }
?: // what should be returned otherwise? emptyList? all? exception?
fun findAllByCountryIdIn(countryIds: Set<String>) = countryIds.ifEmpty {
// what should be returned? emptyList? all entries?
}.let {
missionRepository.findAll(where(countryIdIn(it))) }
}
if
fun findAllByCountryIdIn(countryIds: Set<String>) = if (countryIds.isEmpty()) /* what should be returned? */
else missionRepository.findAll(where(countryIdIn(countryIds))) }
If you just solve the countryIdIn
instead, e.g. by passing an empty element, you give away the control of the query itself to the helper method. If you really want that, fine... but otherwise I wouldn't do that.
Why I wouldn't do that? If I return later to that specific code and read findAll(where(countryIdIn(countryIds)))
. How long does it take me to understand for sure that I return all entries if the set is empty? Fact is: I can't without looking at countryIdIn
itself. But that is my opinion.
Upvotes: 2
Reputation: 81990
Just put a test in the function creating the Specification
if the set is empty and if it is, just return an empty Specification
.
Upvotes: 0