【问题标题】:spring jdbctemplate - how to bind list (consisting of more than 1 parameter) into query argsspring jdbctemplate - 如何将列表(由多个参数组成)绑定到查询参数中
【发布时间】:2022-03-04 08:06:40
【问题描述】:

我想知道如何在 'where' 子句中使用多个参数将对象列表绑定到 sql 中。

Select * from order where order_id = ? and action_code = ?

数据就像

List<Order> orderList = new ArrayList<>();
orderList.add(1,"KP");
orderList.add(2,"DP");
orderList.add(3,"KP");

这是我尝试过的 我有一个订单列表。每个订单都有订单 ID(长)和操作代码(字符串)。现在我需要在 where 子句中以 order id 和 action code 作为参数查询 db。

Select * from order where order_id = ?和 action_code = ?.

我试图在 args 中传递一个对象数组。 [这很有用]。

Object[] args = new Object[ size of orderList ]
int i = 0
for (Order order : orderList)
{
   args[i] = new Object[]{order.getOrderId(), order.getActionCode()};
   i++;
}

我正在触发如下查询

jdbcTemplate.query(sql, args, rowMapper);

当我运行应用程序时,我得到以下错误。

org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [SELECT * where ORD_I = ? AND ACT_C = ?]; SQL state [99999]; error code [17004]; Invalid column type; nested exception is java.sql.SQLException: Invalid column type

但是,如果我按以下方式传递数据,它会起作用

jdbcTemplate.query(sql, new Object[] {orderList.get(0).getOrderId, orderList.get(0).getActionCode()}, rowMapper);

到目前为止我尝试过的 我提供了如下类型 [ 在 DB 中,order_id 是 number(38),action_code 是 Char(2))

int[] types = new int[] { java.sql.Types.NUMERIC, java.sql.Types.CHAR 
};
jdbcTemplate.query(sql, args, types, rowMapper);

我有一个例外说。 [当我用 java.sql.Types.VARCHAR 替换 java.sql.Types.CHAR 时出现同样的错误]

org.springframework.dao.InvalidDataAccessApiUsageException: args and argTypes parameters must match

以下设置有效

 int[] types = new int[] { java.sql.Types.NUMERIC, java.sql.Types.CHAR 
    };
jdbcTemplate.query(sql, new Object[] {orderList.get(0).getOrderId, orderList.get(0).getActionCode()}, types, rowMapper);

我提到了以下问题 How set Array/List in Spring jdbcTemplate as parameter? - 谈论从列表中传递一个参数

how to bind a list of tuples using Spring JDBCTemplate? - 谈论元组。如果我必须使用 tableA.id = tableB.id 和 tableA.id = 查询 2 个表?和tableB.seq_id = ?,那么上面的解决方案不起作用。

我用谷歌搜索了很多,但现在我遇到了障碍。请帮忙。

【问题讨论】:

    标签: spring jdbctemplate


    【解决方案1】:

    我知道此解决方案不适用于列表,但我建议使用 NamedParameterJdbcTemplates 而不是常规的 jdbcTemplate。它更直接且相对较小的变化:

    SQL:

    Select * from order where order_id = :orderId and action_code = :actionCode
    

    orderIDactionCode 对应于您的参数 HashMap 中的 String 键值(如下所示)。

    Java:

    Map<String, Object> parameters = new HashMap<>();
    parameters.put("orderID","KP");
    parameters.put("actionCode","DP");
    
    namedParameterJdbcTemplate.execute(sqlQueryString, parameters);
    

    您将所有参数加载到带有字符串键的键值映射中。

    编辑回答评论:

    为什么不在循环内执行查询,并将结果保存到地图?我正在考虑伪代码:

    for (set in parameterSet){
    parameters.put(set1, set2); 
    ResultSet rs = jdbcTemplate.execute(queryString, parameters); 
    otherMap.put(set1 + set2, rs);}
    

    这里setorderIDactionCode参数的组合,parameterSets是你要查询的orderIDactionCode的所有组合(集合),otherMap是一些您创建的映射集合以将数据持久化到 for 循环之外,使用第一个和第二个集合参数的 concat 作为键,并将结果集作为值。

    为后续 cmets 编辑:

    如果您有 1000 个唯一对,那么这意味着这些唯一参数对中的每一个都应该返回不同的、互斥的结果集。例如,在 WHERE 条件中输入参数 A 和 B 应该返回与输入参数 A 和 C 不同的 ResultSets。我没有看到这方面的捷径。您实际上是在问 1000 个不同的问题,每个问题都有不同的答案。确保获得所有 ResultSet 并只执行一个查询的唯一方法是输入第一个参数和第二个参数的所有可能值:

    WHERE parameter1 IN (... all possible values for parameter1) AND
    parameter2 IN (... all possible values for parameter2)
    

    但是,这会产生比您想要的多得多的行。然后,您必须以编程方式应用您自己的逻辑来过滤掉不属于唯一参数组合集的结果集。

    【讨论】:

    • 抱歉回复晚了...下班了!!!!然而,由于键“orderId”或“actionCode”保持不变,数据在 for 循环期间被覆盖。这个怎么办?
    • 检查我编辑的回复,我试图提出一个解决方案。
    • 如果我有 1000 个 orderid-acioncode 对,那么使用这种方法我需要触发 1000 个选择查询。这是一个很大的性能打击。 spring jdbc 模板是否没有任何功能来适应这种情况,或者我在这里遗漏了什么?非常感谢您的帮助。
    • @YogendraN 我在答案中添加了一个编辑。简而言之,我认为这是不可能的。可以获得更广泛的结果集,然后以编程方式过滤。此外,请考虑执行查询与建立连接的成本。后者更耗费资源。
    猜你喜欢
    • 2013-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-31
    相关资源
    最近更新 更多