Выражение `in`, когда пустой список (спецификация данных весны jpa) - PullRequest
0 голосов
/ 12 сентября 2018

У меня есть этот репозиторий миссии:

@Repository
interface MissionRepository: CrudRepository<MissionEntity, String>, JpaSpecificationExecutor<MissionEntity>

В моем классе обслуживания миссий я хотел бы получить все миссии, у которых есть countryId части данного аргумента Set:

fun findAllByCountryIdIn(countryIds: Set<String>): List<MissionEntity> =
        missionRepository.findAll(where(countryIdIn(countryIds)))
}

Откуда countryIdIn (используя предикат in):

class MissionSpecifications {
    companion object {
        fun countryIdIn(countryIds: Set<String>): Specification<MissionEntity> =
            Specification { root, _, _ -> root.get<String>("countryId").`in`(countryIds) }
    }
}

Но когда Set пуст, я получил предсказуемую ошибку sql. Есть ли способ активировать предложение where только тогда, когда данный набор не пуст? Без проверки if / else? Может быть, мой синтаксис спецификации может быть улучшен, чтобы избежать этой ошибки sql?

Ответы [ 3 ]

0 голосов
/ 12 сентября 2018

Я бы предпочел вернуться раньше.Так что просто не добавляйте где, если вам это не нужно в первую очередь.Вы можете сделать это несколькими способами, например, используя takeIf, простой if, when и т. Д.

Просто перечислите некоторые образцы:

  • takeIf

    fun findAllByCountryIdIn(countryIds: Set<String>) = countryIds.takeIf { it.isNotEmpty() }
                 ?.let { missionRepository.findAll(where(countryIdIn(it))) } 
                 ?: // what should be returned otherwise? emptyList? all? exception?
    
  • ifEmpty (Kotlin> = 1,3)

    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))) }
    

Если вы просто решите вместо countryIdIn, например, пропустив пустой элемент, вы отдадите управлениесамого запроса к вспомогательному методу.Если ты действительно этого хочешь, хорошо ... но в противном случае я бы этого не сделал.

Почему я бы этого не сделал?Если я позже вернусь к этому конкретному коду и прочту findAll(where(countryIdIn(countryIds))).Сколько времени у меня займет, чтобы понять наверняка, что я возвращаю все записи, если набор пуст?Факт: я не могу, не глядя на countryIdIn сам.Но это мое мнение.

0 голосов
/ 12 сентября 2018

Другое решение будет:

@Repository
interface MissionRepository: JpaRepository<MissionEntity, String> {
    fun findByCountryIdIn(countryIds: Set<String>, pageable: Pageable): Page<MissionEntity>
}

, где вы можете добавить нумерацию страниц.

0 голосов
/ 12 сентября 2018

Просто поместите тест в функцию, создающую Specification, если набор пуст и если он есть, просто верните пустой Specification.

...