Spring Boot中具有WHERE条件的本机查询中的列表中的元组

时间:2019-03-23 16:16:13

标签: sql spring-boot jdbc kotlin spring-data-jpa

当向PostgreSQL发送纯SQL时,如下所示:

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做同样的事情时,它会失败。这是我的最小示例(科特琳):

实体:

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 个答案:

答案 0 :(得分:1)

感谢this commentJB 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模式下可以在实际的Postgres和H2中工作。


另一个选择是切换到embedded-database-spring-test并使用其嵌入式Postgres进行测试。然后,原始语法(使用VALUES)也可以使用。