空列表时的表达式`in`(Spring Data JPA规范)

时间:2018-09-12 09:18:56

标签: jpa kotlin spring-data-jpa jpql

我有这个任务库:

@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 :(得分:1)

我宁愿早点回来。因此,如果您首先不需要,请不要添加位置。您可以通过多种方式进行操作,例如使用takeIf,简单的ifwhen等。

仅列出一些示例:

  • 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,例如通过传递一个空元素,您可以将查询本身的控制权交给helper方法。如果您真的想要那个,那很好...但是否则我不会那样做。

我为什么不这样做?如果稍后再返回该特定代码并阅读findAll(where(countryIdIn(countryIds)))。如果集合为空,我要花多长时间才能确定我会返回所有条目?事实是:我不能不看countryIdIn本身。但这是我的看法。

答案 1 :(得分:0)

如果集合为空,则只需对创建Specification的函数进行测试,如果集合为空,只需返回一个空的Specification

答案 2 :(得分:0)

另一种解决方案是:

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

您可以在其中添加分页。