此查询在 SQL Developer 中运行良好:
select * from MYTABLE where (field1, field2) IN (('A', '1'), ('B','2'), ('C','3')) ;
但是当我尝试从 java 调用它时,我遇到了异常。
public List<MYVO> callDB(List<String> sourceAndIdList) {
System.out.println(sourceAndIdList);
String query = "select * from MYTABLE where (field1, field2) IN (:source_monitorId_list)";
Map<String, List<String>> namedParameters = Collections.singletonMap("source_monitorId_list", sourceAndIdList);
return this.namedParameterJdbcTemplate.query(query , namedParameters, new RowMapper<MYVO>() {
@Override
public MYVO mapRow(ResultSet rs, int rowNum) throws SQLException {
....
}
});
}
打印我收到的清单:
[('A', '1'), ('B', '2'), ('C', '3')]
例外:
严重:servlet [selfservice] 的 Servlet.service() 在上下文中 路径[/mymonitoring]抛出异常[请求处理失败; 嵌套异常是 org.springframework.jdbc.BadSqlGrammarException: 准备语句回调;错误的 SQL 语法 [select * from MYTABLE 其中 (field1, field2) IN (?, ?, ?)];嵌套异常是 java.sql.SQLSyntaxErrorException:ORA-00920:无效的关系 运算符 ] 的根本原因是 java.sql.SQLSyntaxErrorException: ORA-00920: 无效的关系运算符
编辑:这不是重复的,因为我正在寻找带有弹簧
的解决方案,用于具有多个 IN 子句的查询,并且参数的大小仅在运行时已知。NamedParameterJdbcTemplate
您不能在“IN”中使用这样的绑定参数。
无论你这样做:
IN ((:p1, :p2), (:p3,:p4), (:p5,:p6))
但它假设您确切知道有多少个项目(在本例中为 3),或者您在 SQL 字符串中“具体化”参数:
String query = "select * from MYTABLE where (field1, field2) IN (('A', '1'), ('B', '2'), ('C', '3'))";
你需要使用foreach并替换sql,例如
`
String query = "select * from MYTABLE where (field1, field2) IN (:source_monitorId_list)";
MapSqlParameterSource paramSource = new MapSqlParameterSource();
StringBuilder sql1 = new StringBuilder();
for(int i=0, i < sourceAndIdList.length; i--) {
if (i == sourceAndIdList.length-1) {
sql1.append("(:field1" + i);
sql1.append(", ");
sql1.append(":field2" + i + ")");
}else {
sql1.append("(:field1" + i);
sql1.append(", ");
sql1.append(":field2" + i + "),");
}
String field_temp = sourceAndIdList[i].replace("(", "");
String field = field_temp..replace(")", "");
String field_value_1 = field.split(", ")[0];
String field_value_2 = field.split(", ")[1];
paramSource.addValue(":field1"+ i, field_value_1);
paramSource.addValue(":field2"+ i, field_value_2);
}
// you will get like this (:field10, :field20), (:field11, :field21), (:field12, :field22)
String currentSql = query.replace(":source_monitorId_list", sql1);
RowMapper<MYVO> mapper = new RowMapper<MYVO>(){};
this.namedParameterJdbcTemplate.query(currentSql, paramSource, mapper);
`