Собственный запрос в Spring Boot с условием WHERE для кортежа в списке - PullRequest
0 голосов
/ 23 марта 2019

При отправке простого SQL в PostgreSQL, как показано ниже:

CREATE TABLE things (
    id      BIGINT PRIMARY KEY NOT NULL,
    foo     BIGINT NOT NULL,
    bar     BIGINT NOT NULL
);


INSERT INTO things VALUES (9900, 1, 2);
INSERT INTO things VALUES (9901, 3, 4);
INSERT INTO things VALUES (9902, 1, 4);
SELECT * FROM things WHERE foo IN (1, 2);
SELECT * FROM things WHERE (foo, bar) IN (VALUES (1, 2), (3, 4));

работает как положено.

Однако при попытке сделать то же самое с помощью Spring Boot происходит сбой. Вот мой минимальный пример (Kotlin):

Сущность:

import org.springframework.data.jpa.domain.AbstractPersistable
import javax.persistence.Entity
import javax.persistence.Table

@Entity
@Table(name = "things")
class Thing(
        val foo: Long,
        val bar: Long
) : AbstractPersistable<Long>()

Хранилище:

import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Query

interface ThingRepository : JpaRepository<Thing, Long> {

    @Query(nativeQuery = true, value = "SELECT * FROM things WHERE foo IN (1, 2);")
    fun selectNativeByFoo(): Iterable<Thing>

    @Query(nativeQuery = true, value = "SELECT * FROM things WHERE (foo, bar) IN (VALUES (1, 2), (3, 4));")
    fun selectNativeByFooAndBar(): Iterable<Thing>
}

Вызов selectNativeByFoo работает нормально, но вызов selectNativeByFooAndBar завершается неудачно со следующим исключением:

org.springframework.dao.InvalidDataAccessResourceUsageException: could not prepare statement; SQL [SELECT * FROM things WHERE (foo, bar) IN (VALUES (1, 2), (3, 4));]; nested exception is org.hibernate.exception.SQLGrammarException: could not prepare statement


Caused by: org.h2.jdbc.JdbcSQLException: Invalid parameter count for "VALUES", expected count: "1"; SQL statement:
SELECT * FROM things WHERE (foo, bar) IN (VALUES (1, 2), (3, 4)); [7001-197]

Что я делаю не так?

1 Ответ

1 голос
/ 23 марта 2019

Благодаря этому комментарию от JB Nizet , я смог его решить.

Используемый синтаксис

SELECT * FROM things WHERE (foo, bar) IN (VALUES (1, 2), (3, 4));

толькоподдерживается реальным PostgreSQL, а не H2, который я использовал для своих тестов, даже при

spring.datasource.url: jdbc:h2:mem:db;MODE=PostgreSQL

Изменение его на

SELECT * FROM things WHERE (foo, bar) IN ((1, 2), (3, 4));

позволяет работать как в реальных Postgres, так и в H2в режиме Postgres.


Другой вариант - переключиться на embedded-database-spring-test и использовать встроенный Postgres для тестирования.Тогда оригинальный синтаксис (с использованием VALUES) также работает.

...