如何在Spring JDBC本机Query IN参数中处理999大小?

时间:2018-07-25 16:46:41

标签: java oracle spring-jdbc

我正在使用Spring Batch + Spring JDBC。在我的项目中,我们要将“客户”列表传递给本机SQL的IN查询。在IN参数中,我们最多可以传递999条记录,而其余列表则需要再次处理。

我开发了以下代码,但是如果我有2000条以上的记录,则效果不佳。如何进行动态处理,所以如果代码中包含任何列表值,则应生成结果?

if(accNumList.size() < 999) {
    Map<String, Set<Integer>> singletonMap = Collections.singletonMap("valSet1", accNumList);
    Map<String, Object> paramMap = new HashMap<>();
    paramMap.putAll(singletonMap);
    paramMap.put("isFlag", "Y");

    List<Map<String, Object>> queryForMap = namedParameterJdbcTemplate.queryForList(sql, paramMap);
}else {
    int sizeOfRecords = accNumList.size();
    // convert set to List
    List<Integer> data = new ArrayList<>(accNumList);
    List<Integer> subItems = data.subList(0, 999);

    Map<String, List<Integer>> singletonMap = Collections.singletonMap("valSet1", subItems);
    Map<String, Object> paramMap = new HashMap<>();
    paramMap.putAll(singletonMap);  
    List<Map<String, Object>> queryForMap = namedParameterJdbcTemplate.queryForList(sql, paramMap);

    // remaining
    int remaining = sizeOfRecords - 999;
    List<Integer> newsubItems = data.subList(1000, remaining);
    Map<String, List<Integer>> newsingletonMap = Collections.singletonMap("valSet1", newsubItems);

    Map<String, Object> newparamMap = new HashMap<>();
    newparamMap.putAll(newsingletonMap);

    List<Map<String, Object>> newqueryForMap = namedParameterJdbcTemplate.queryForList(sql, newparamMap);

    //final
    List<Map<String, Object>> queryForMapFinal = new ArrayList<>();
    queryForMapFinal.add(paramMap);
    queryForMapFinal.add(newparamMap);
}

1 个答案:

答案 0 :(得分:1)

解决IN限制的效率很低,用Java构建JDBC查询并不总是适合此工作的合适工具。请考虑以下内容:

  1. 数千个绑定值将导致潜在的兆字节SQL。将此SQL发送到数据库将花费很长时间。数据库可能比根据Tom's answer to "Limit and conversion very long IN list: WHERE x IN ( ,,, ...)" question执行SQL文本花费的时间更长。

  2. 由于SQL解析,效率低下。

  3. 不仅解析此长的SQL需要花费很长时间,而且每次调用都有不同数量的绑定参数,这些参数将分别解析和计划(请参阅this article which explains it)。

  4. SQL语句中对绑定参数有硬限制。您可以重复执行OR几次,以达到IN的限制,但有时会达到SQL语句的限制。

对于这些类型的查询,通常最好创建temporary tables。在查询之前创建一个,将所有标识符插入其中,并将其与查询中的实体表连接起来以模拟IN条件。

理想情况下,您可以用存储过程替换Java代码,尤其是当您从数据库中提取成千上万个标识符只是为了在下一个查询中将它们传递回数据库时。