PostgreSQL, Spring Data JPA: целое значение null, интерпретируемое как bytea - PullRequest
0 голосов
/ 06 декабря 2018

В PostgreSQL у меня есть таблица

CREATE TABLE public.my_table
(
    id integer NOT NULL,
    ...

Я хочу выполнить запрос: Показать строки с данным идентификатором.Если id ноль, покажите мне все строки.

Я пробовал это с

public interface MyRepository extends JpaRepository<MyTable, Integer> {

    @Query(value = "SELECT * FROM my_table WHERE (?1 IS NULL OR id = ?1)", nativeQuery = true)
    List<MyTable> findAll(Integer id);

Если id != null, все в порядке.Но если id == null, я получу ошибку

org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:261) ~[spring-orm-4.3.13.RELEASE.jar:4.3.13.RELEASE]
...
Caused by: org.hibernate.exception.SQLGrammarException: could not extract ResultSet
    at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:106) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
...
Caused by: org.postgresql.util.PSQLException: ERROR: operator does not exist: integer = bytea
  Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts.
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2440) ~[postgresql-42.2.5.jar:42.2.5]
...

Очевидно, что оценка короткого замыкания не работает и null преобразуется в bytea.

В качестве обходного пути я изменилсязначение запроса в

SELECT * FROM my_table WHERE (?1 IS NULL OR id = (CAST (CAST(?1 AS character varying) AS integer)))

Но это нехорошо, потому что int приводится к string и снова к int.У вас есть лучшее решение, например, лучший приведение или SQL-запрос?

1 Ответ

0 голосов
/ 06 декабря 2018

Другой обходной путь для этого - создать запрос вручную из EntityManager (em в примере) и вызвать setParameter один раз с ненулевым значением, затем снова с реальным значением.

private static final Integer exampleInt = 1;

List<MyTable> findAll(Integer id) {
    return em.createNativeQuery("SELECT * FROM my_table WHERE (:id IS NULL OR id = :id)", MyTable.class)
            .setParameter("id", exampleInt)
            .setParameter("id", id)
            .resultList();
}

Это гарантирует, что Hibernate узнает тип значения в следующий второй раз, когда он вызывается, даже если он равен нулю.

Ошибка на сервере PostgreSQL, а не в Hibernate, но они отказалисьисправить это, потому что он работает как задумано.У вас просто есть несколько сотен типов SQL NULL на сервере, и они в основном несовместимы друг с другом, даже если это одно специальное значение.

...