JPA-запрос для PostgreSQL - PullRequest
       13

JPA-запрос для PostgreSQL

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

У меня есть следующий запрос, который работает при запуске через Postgres-

select * from my_schema.my_table where (jsonb_1 @> '"789"' or jsonb_2 @> '"789"') and (status != 'BAD_STATUS');

Он проверяет, есть ли значение "789" в примере jsonb_1 (список строк): ["456", "789"] или "789" в jsonb_2 (список строк) пример: ["123", "456"] и со статусом не BAD_STATUS.Я пытаюсь представить тот же запрос в Spring Data JPA (версия 1.5.6.RELEASE) и пробовал два ниже, но получаю исключения.

Запрос1:

@Query(value = "select * from my_schema.my_table where (jsonb_1 @> :jsonbValue or jsonb_2 @> :jsonbValue) and (status != :badStatus)", nativeQuery = true)
List<MyEntity> findAllByJsonbValueAndStatusNot(@Param("jsonbValue") String jsonbValue, @Param("badStatus") String badStatus);

Исключение:

2018-10-12 07:41:18,750 DEBUG http-nio-9030-exec-1 - [correlationId:, errorCode:] - org.hibernate.engine.jdbc.spi.SqlExceptionHelper.logExceptions.122 - could not extract ResultSet [n/a]
org.postgresql.util.PSQLException: ERROR: operator does not exist: jsonb @> character varying
  Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts.
  Position: 60
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2455)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2155)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:288)
    at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:430)
    at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:356)
    at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:168)
    at org.postgresql.jdbc.PgPreparedStatement.executeQuery(PgPreparedStatement.java:116)
    at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeQuery(ProxyPreparedStatement.java:52)
    at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeQuery(HikariProxyPreparedStatement.java)
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:70)
    at org.hibernate.loader.Loader.getResultSet(Loader.java:2117)
    at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1900)
    at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1876)
    at org.hibernate.loader.Loader.doQuery(Loader.java:919)[...]

Запрос2:

@Query(value = "select * from my_schema.my_table where (jsonb_1 @> ?1 or jsonb_2 @> ?1) and (status != ?2)", nativeQuery = true)
List<MyEntity> findAllByJsonbValueAndStatusNot(String jsonbValue, String badStatus);

Исключение:

2018-10-12 07:29:41,126 ERROR http-nio-9030-exec-1 - [correlationId:, errorCode:] - com.my.services.common.exception.ExceptionHandler.handleAppErrors.39 - Internal server error occurred
org.springframework.dao.InvalidDataAccessApiUsageException: Name for parameter binding must not be null or empty! On JDKs < 8, you need to use @Param for named parameters, on JDK 8 or better, be sure to compile with -parameters.; nested exception is java.lang.IllegalArgumentException: Name for parameter binding must not be null or empty! On JDKs < 8, you need to use @Param for named parameters, on JDK 8 or better, be sure to compile with -parameters.
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:384)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:246)

Caused by: java.lang.IllegalArgumentException: Name for parameter binding must not be null or empty! On JDKs < 8, you need to use @Param for named parameters, on JDK 8 or better, be sure to compile with -parameters.
at org.springframework.util.Assert.hasText(Assert.java:181)
at [...]`

Ответы [ 2 ]

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

Похоже на проблему с типизациейПопробуйте это

@Query(value = "select * from my_schema.my_table where (jsonb_1 @> :jsonbValue\:\:jsonb or jsonb_2 @> :jsonbValue\:\:jsonb) and (status != :badStatus)", nativeQuery = true)

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

@Query(value = "select * from my_schema.my_table where (jsonb_1 @> cast(:jsonbValue as jsonb) or jsonb_2 @> cast(:jsonbValue as jsonb)) and (status != :badStatus)", nativeQuery = true)
0 голосов
/ 12 октября 2018

Это говорит о том, что вы не можете использовать оператор @> для сравнения строки и jsonb (который должен быть одним из ваших типов столбцов в БД).Вам нужно будет привести строку как jsonb или jsonb к строке, чтобы выполнить сравнение.

Postgres Docs при приведении типов

Вы можете использовать LIKEоператор для сравнения строк в приведенной строке:

WHERE jsonb::varchar LIKE 'jsonbValue'

LIKE оператор

или использование оператора @> для приведения jsonb:

WHERE jsonb @> :jsonbValue::jsonb

Функции JSONb в postgres

РЕДАКТИРОВАТЬ:

Для второго запроса вы используете именованные параметры, которые не существуют в вашем именованном запросе.Либо замените ?1 на :jsonbValue, либо удалите аннотации @Param.

...