我正在使用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);
}
答案 0 :(得分:1)
解决IN
限制的效率很低,用Java构建JDBC查询并不总是适合此工作的合适工具。请考虑以下内容:
数千个绑定值将导致潜在的兆字节SQL。将此SQL发送到数据库将花费很长时间。数据库可能比根据Tom's answer to "Limit and conversion very long IN list: WHERE x IN ( ,,, ...)" question执行SQL文本花费的时间更长。
由于SQL解析,效率低下。
SQL语句中对绑定参数有硬限制。您可以重复执行OR
几次,以达到IN
的限制,但有时会达到SQL语句的限制。
对于这些类型的查询,通常最好创建temporary tables。在查询之前创建一个,将所有标识符插入其中,并将其与查询中的实体表连接起来以模拟IN
条件。
理想情况下,您可以用存储过程替换Java代码,尤其是当您从数据库中提取成千上万个标识符只是为了在下一个查询中将它们传递回数据库时。