在RowMapper中使用查询

在java中我会做类似下面的事情来迭代resultset并形成查询,

 public Map<String, List> fun(){ Map<String, List> map = new TreeMap<String, List>(); LinkedHashSet set = new LinkedHashSet(); String sql = "select distinct(column) from table where conditions orderby column "; ResultSet rslt = stmt.executeQuery(sql); while (rslt.next()) { al.add(rslt.getString(1)); } for (String s : al) { List list = new ArrayList(); String sql2 = "select * from table where column="+s; ResultSet rslt2 = stmt.executeQuery(sql2); while (rslt2.next()) { MODEL obj = new MODEL(); // set values to setters from resultset list.add(obj); } map.put(s, list); } return map; } 

我使用单独查询的原因是,我将不同的值添加到地图键及其对应的值(作为List)到地图的值。 注意 (在结果中它具有column1的重复值),但我需要将它们存储为map键,从而使其成为唯一的。 我还需要所有相关的值,以便填充列表

如何使用JdbcTemplate实现相同的function,

提前致谢

正如多人所说,你的解决方案效率不高,虽然它可能有效但你基本上陷入了1 + N选择问题的陷阱。 1个查询检索一些id,然后为每个id检索另一个查询(因此1 + N选择)。

最好只写一个查询,一次性检索所有内容。 查看您的代码,您有以下2个查询,根据它们的外观,它们在同一个表上运行。

 String sql1 = "select distinct(column) from table where conditions orderby column "; String sql2 = "select * from table where column="+s 

现在,您可以将第一个查询作为第二个查询的子选择

 String sql = "select * from table where column in (select distinct(column) from table where conditions) order by column"; 

但是,从它的外观来看,将第二个查询中的where子句放在一起也是可能的(或者甚至更容易)。

 String sql = "select * from table where conditions order by column"; 

您现在可能会获取您的密钥(在Map )获取多个值。 您可以自己使用ResultSetExtractor循环对结果执行两项操作,或者使用RowCallbackHandler为您执行迭代。

您需要做的只是迭代结果(或让JdbcTemplate为您做这件事)为您的键列检查Map是否已经存在List 。 如果是先添加一行,如果不是先创建List并将其添加到结果Map

 public Map> fun(){ final Map> map = new TreeMap>(); String sql = "select * from table where conditions order by column"; getJdbcTemplate().query(sql, new RowCallbackHandler() { public void processRow(ResultSet resultSet) throws SQLException { String key = rs.getString("column"); List rows = map.get(key); if (rows == null) { rows = new new ArrayList(); map.put(key, rows); } MODEL obj = new MODEL(); // set values to setters from resultset rows.add(obj); }, "arguments"); return map; } 

另一个解决方案,只有在’列’也是MODEL类的一部分时才有效。 这样你就可以使用RowMapper获取所有MODEL对象的List ,然后进行分区。 您可以使用Google Guava使其更容易实现,或者如果您使用的是Java 8,则可以使用新的流api。

正如@geoand所说,最好的事情(无论是直接的JDBC代码还是使用JDBCTemplate)都是使用Join进行单个查询。

但是,如果您在评论中提到,您绝对肯定第一个查询的结果集总是很小(可疑),那么您可以将从第一个查询中检索到的值存储在列表中,然后执行第二个查询带有“in”子句,使用列表作为参数。 这将导致两个查询。

在任何情况下,您实际上不希望对从第一个查询返回的每个项目执行单独的查询,因为这将非常慢,即使对于少量项目也是如此。 但是,如果您认为必须 ,则将第一个查询的结果存储在列表中,然后为列表中的每个项目发出另一个查询。

TLDR; 不,JDBCTemplate不提供执行所需操作的机制,主要是因为它通常被认为是编程反模式的规范示例。