ОШИБКА: оператор не существует: boolean = bytea в запросе spring jpa и postgres - PullRequest
0 голосов
/ 09 мая 2020

Когда я выполняю следующий запрос непосредственно в postgres, он работает нормально, но когда я запускаю с JPA, возникает ошибка ниже.

Пример запроса:

select
    *
from
    products
where
    clientId = :clientId
    and ((:status is null
    and status in (true,
    false))
    or status = :status)
    and ((:anotherStatus is null
    and anotherStatus in (true,
    false))
    or anotherStatus = :anotherStatus);

Ошибка:

ОШИБКА org.hibernate.engine.jdb c .spi.SqlExceptionHelper - ОШИБКА: оператор не существует: boolean = bytea Подсказка: ни один оператор не соответствует заданное имя и типы аргументов. Возможно, вам потребуется добавить явное приведение типов.

Настроено в JPA следующим образом:

@Query(value="select * from products where clientId = :clientId and ((:status is null and status in (true, false)) or status = :status) and ((:anotherStatus is null and anotherStatus in (true, false)) or anotherStatus = :anotherStatus)",nativeQuery=true)
List<Products> fetchProducts(@Param("clientId") Long clientId, @Param("status") Boolean status, @Param("anotherStatus") Boolean anotherStatus);

В основном я пытаюсь достичь, когда пользователь отправляет параметр как true, фильтровать продукты с true (активен) или как false (в активном состоянии), и когда пользователь ничего не отправляет (что составляет null), выбирает все продукты (true и false)

1 Ответ

1 голос
/ 11 июня 2020

Имейте в виду, что null = null, true = null и false = null все вычисляют как null, что рассматривается как false в предложении where. Если вам нужно что-то еще, перефразируйте свой вопрос. Давайте посмотрим на таблицу истинности для (:status is null and status in (true,false)) or status = :status.

|-------------|-------------|-------------|
|   :status   |   status    |   result    |
|-------------|-------------|-------------|
|    null     |    null     |    false    |
|    null     |    true     |    true     |
|    null     |    false    |    true     |
|    true     |    null     |    false    |
|    true     |    true     |    true     |
|    true     |    false    |    false    |
|    false    |    null     |    false    |
|    false    |    true     |    false    |
|    false    |    false    |    true     |
|-------------|-------------|-------------|

Другими словами, вам нужно предложение, которое всегда возвращает false, когда status равно null. Это оставляет true, если :status равно null, или истину, если :status и status имеют одинаковое значение.

status is not null and (:status is null or status = :status)

в качестве альтернативы

status is not null and coalesce(:status, status) = status

Обратите внимание, что это все еще не работает для описанной вами ошибки, потому что :status привязан как BYTEA Hibernate, когда вы передаете null в Java. Вы можете обойти это, выполнив двойное приведение.

CAST(CAST(:status AS CHARACTER VARYING) AS BOOLEAN)

Если это именно то, что вы намеревались, результат будет:

SELECT *
FROM products
WHERE status IS NOT NULL
AND anotherStatus IS NOT NULL
AND COALESCE(CAST(CAST(:status AS CHARACTER VARYING) AS BOOLEAN), status) = status
AND COALESCE(CAST(CAST(:anotherStatus AS CHARACTER VARYING) AS BOOLEAN), anotherStatus) = anotherStatus
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...