我正在尝试创建一个使用CTE结构的查询。查询如下所示:
with data (a, b, c) as (
values ('a1', 'b1', 'c1'), ('a2', 'b2', 'c2')
)
select * from data
这个查询当然是简化的,为了保持这一点。
以下效果很好:
@Component
public class QueryTest {
private NamedParameterJdbcTemplate template;
@Autowired
public QueryTest(final DataSource source) {
template = new NamedParameterJdbcTemplate(source);
}
@Scheduled(fixedRate = 1000)
public void test() {
MapSqlParameterSource p = new MapSqlParameterSource()
.addValue("data", Arrays.asList(
new Object[]{"a1", "b1", "c1"},
new Object[]{"a2", "b2", "c2"}));
System.out.println(template.query("with data (a, b, c) as (values :data) select * from data", p, (set, index) -> new Object()));
}
}
但是,如果我在data
命名参数中只有一行,则它不起作用:
@Component
public class QueryTest {
private NamedParameterJdbcTemplate template;
@Autowired
public QueryTest(final DataSource source) {
template = new NamedParameterJdbcTemplate(source);
}
@Scheduled(fixedRate = 1000)
public void test() {
MapSqlParameterSource p = new MapSqlParameterSource()
.addValue("data", Arrays.asList(
new Object[]{"a1", "b1", "c1"}));
System.out.println(template.query("with data (a, b, c) as (values :data) select * from data", p, (set, index) -> new Object()));
}
}
我收到以下错误:
Caused by: org.postgresql.util.PSQLException: ERROR: syntax error at or near "$1"
Position: 32
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2284) ~[postgresql-9.4.1208.jar:9.4.1208]
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2003) ~[postgresql-9.4.1208.jar:9.4.1208]
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:200) ~[postgresql-9.4.1208.jar:9.4.1208]
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:424) ~[postgresql-9.4.1208.jar:9.4.1208]
at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:161) ~[postgresql-9.4.1208.jar:9.4.1208]
at org.postgresql.jdbc.PgPreparedStatement.executeQuery(PgPreparedStatement.java:114) ~[postgresql-9.4.1208.jar:9.4.1208]
at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeQuery(ProxyPreparedStatement.java:52) ~[HikariCP-2.5.1.jar:?]
at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeQuery(HikariProxyPreparedStatement.java) ~[HikariCP-2.5.1.jar:?]
at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:688) ~[spring-jdbc-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:629) ~[spring-jdbc-4.2.5.RELEASE.jar:4.2.5.RELEASE]
知道这里出了什么问题吗?有没有更好的方法来执行这些类型的查询?
更新
我在postgres中启用了日志记录,看起来第一个查询被解析为:
with data (a, b, c) as (values ($1, $2, $3), ($4, $5, $6)) select * from data
但第二个被解决为:
with data (a, b, c) as (values $1, $2, $3) select * from data
看起来周围的括号丢失了吗?
答案 0 :(得分:0)
问题在于您使用Arrays.asList
。传入多个对象数组时,您将获得一个对象数组列表。如果只传入单个对象数组,则会获得数组内容的列表,而不是单个对象数组的列表。它将数组解释为单独的varargs而不是一个参数。如果您打印出Arrays.asList(new Object[]{"a1", "b1", "c1"})
给出的内容,它将如下所示:[a1,b1,c1]。
对于单个数组用例,请尝试使用Collections.singletonList
创建列表,或者创建ArrayList
,然后使用add
方法添加数据值。
MapSqlParameterSource p = new MapSqlParameterSource()
.addValue("data", Collections.singletonList(new Object[]{"a1", "b1", "c1"}));