JPA @Query со сложным обнуляемым объектом - PullRequest
0 голосов
/ 17 октября 2018

Я создаю репозиторий с запросом getAll, в котором для фильтрации используется параметр сложного типа, например:

@Query("""
    SELECT c FROM City c
    WHERE :filter IS NULL OR c.code LIKE %:#{#filter.code}%
    """)
fun getAllCitiesFiltered(@Param("filter") filter: MyFilter?) : List<City>

Класс MyFilter представляет собой простой POJO:

class MyFilter {
    var code: String? = null
    var description: String? = null
}

В какой-то момент в моем коде я вызываю getAllCitiesFiltered(filter), и это filter может быть нулевым или может иметь одно из его свойств, равное нулю.У меня два вопроса:

  • Как я могу справиться с тем, что filter обнуляем?Теперь так (как выше), когда ему передается значение null, я получаю исключение EL1007E: Property or field 'code' cannot be found on null
  • Есть ли в HQL менее уродливый способ справиться с тем, что свойства code и description могут быть нулевыми, а когда они нулевыми, я не хочу фильтровать их?Единственный способ, которым я сейчас занимаюсь, - это делать что-то вроде ... WHERE filter.code IS NULL or filter.code LIKE %c.code%

Я новичок в JPA и не уверен, что использование @Query - лучший подход здесь.Я открыт для предложений, чтобы изменить это также.

Спасибо!

РЕДАКТИРОВАТЬ после предложения Алана Хэя

Я использую QueryDSL и,Исходя из C # / LINQ фона, найти его здорово.«Проблема» в том, что я делаю что-то вроде этого:

val city = QCity.city
var query = JPAQuery<City>(entityManager).from(city)

if (filter?.code != null)
    query = query.where(city.code.eq("BH"))

if (filter?.description != null)
    query = query.where(city.description.eq("Belo Horizonte"))

Есть ли лучший способ написать это, кроме переключения и если / else'ing?

Спасибо!

1 Ответ

0 голосов
/ 18 октября 2018

Лучший способ - использовать метод интерфейса по умолчанию:

interface CityJpaRepository : JpaRepository<City, Int> {
  fun findByCodeLike(code: String) : List<City>

  fun findByFilter(filter: MyFilter?) : List<City> {
    return filter?.code?.let { findByCodeLike(it.code) } ?: findAll()
  }
}
...