使用带有休眠 SQL 查询的多列的参数化 IN 子句

Posted

技术标签:

【中文标题】使用带有休眠 SQL 查询的多列的参数化 IN 子句【英文标题】:Parameterized IN clause using multiple columns with hibernate SQL query 【发布时间】:2017-06-08 10:51:55 【问题描述】:

如何在多列IN子句的情况下为休眠SQL查询设置参数?

例如,SQL 查询应该如下生成:

SELECT * FROM TABLE TA WHERE (TA.COLUMN1 , TA.COLUMN2) IN ((C1v, C2v), (C1v, C2v), .....);

我看到这可以通过 here 中提到的 Spring jdbcTemplate 来实现,但我希望在 Hibernate SQL Query 中实现这一点。

我尝试了以下场景,但它们都不适合我:

String sql = "SELECT * FROM TABLE TA WHERE (TA.COLUMN1 , TA.COLUMN2) IN (:ids)";
// 1. List of BigDecimal array's
List<BigDecimal[]> ids = new ArrayList<>();
BigDecimal[] bd1 = new BigDecimal(100119401), new BigDecimal(2);
BigDecimal[] bd2 = new BigDecimal(100119000), new BigDecimal(1);
ids.add(bd1);
ids.add(bd2);

Query query = session.createSQLQuery(sql);
query.setParameterList("ids", ids);

// 2. List of Object arrays
List<Object []> ids = new ArrayList<>();
Object [] bd1 = new BigDecimal(100119401), new BigDecimal(2);
Object [] bd2 = new BigDecimal(100119000), new BigDecimal(1);
ids.add(bd1);
ids.add(bd2);

Query query = session.createSQLQuery(sql);
query.setParameterList("ids", ids);

// 3. List of inner lists with ids
List<BigDecimal> ob1 = new ArrayList<BigDecimal>();
ob1.add(new BigDecimal(100119401));ob1.add(new BigDecimal(2));
List<BigDecimal> ob2 = new ArrayList<BigDecimal>();
ob2.add(new BigDecimal(100119401));ob2.add(new BigDecimal(2));
List<List<BigDecimal>> ids = new ArrayList<List<BigDecimal>>(); 
ids.add(ob1);ids.add(ob2);

Query query = session.createSQLQuery(sql);
query.setParameterList("ids", ids);

在所有情况下都会出现 “ORA-00920:无效的关系运算符” 错误。

例外:

Caused by: java.sql.SQLSyntaxErrorException: ORA-00920: invalid relational operator

    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:450)
    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:399)
    at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1017)
    at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:655)
    at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:249)
    at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:566)
    at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:215)
    at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:58)
    at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:776)
    at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:897)
    at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1034)
    at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3820)
    at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3867)
    at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1502)
    at org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
    at org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:82)
    ... 141 more

【问题讨论】:

这可能会有所帮助.. ***.com/a/26416368/2893693 如果我只能设置一个元组,则查询正在执行。 'BigDecimal[] arr1 = new BigDecimal(100119401), new BigDecimal(2); query.setParameterList("ids", arr1);'.我认为我们应该使用二维数组。谁能建议如何将二维数组设置为查询? 【参考方案1】:

类似的东西应该可以工作:

String sql = "SELECT * FROM TABLE TA WHERE CONCAT(TA.COLUMN1, '|', TA.COLUMN2) IN (:values)";
List<String> values = new ArrayList<>();
values.add("100119401|2");
values.add("100119000|1");

// ...

Query query = session.createSQLQuery(sql);
query.setParameterList("values", values);

注意:确保使用的分隔符(此处为 |)不在您的数据中

【讨论】:

感谢 RC。这适用于查询 String sql = "SELECT * FROM TABLE TA WHERE CONCAT(CONCAT(TA.COLUMN1, '|'), TA.COLUMN2) IN (:values)"; .但是使用这种方法会对查询产生很大的性能影响:( 答案是给你的想法,而不是一个现成的使用 sn-p ;) 你可以[并且应该如果全表扫描产生性能问题]在连接列上创建一个基于函数的索引

以上是关于使用带有休眠 SQL 查询的多列的参数化 IN 子句的主要内容,如果未能解决你的问题,请参考以下文章

带有子查询的休眠标准

带有子查询的休眠选择查询?

SQL 基础之使用子查询检索数据(二十二)

Sql Server参数化查询之where in和like实现详解

Sql Server参数化查询之where in和like实现详解

Sql Server参数化查询之where in和like实现详解