如何让JdbcTemplate的queryForList仅返回String类型对象?
如何让JdbcTemplate返回Map<String, String>类型的结果列表
这个问题我之前在项目里也碰到过,直接传Map<String, String>.class确实行不通——因为Java的泛型类型信息在编译时会被擦除,JdbcTemplate没办法识别到你指定的泛型参数,所以编译会直接报错。下面给你几个实用的解决方案:
方案一:自定义RowMapper实现转换
queryForList的底层其实依赖RowMapper处理结果集,我们可以自己实现一个RowMapper,把结果集中的每一列都转成String类型:
List<Map<String, String>> result = jdbcTemplate.query(sql, params, new RowMapper<Map<String, String>>() { @Override public Map<String, String> mapRow(ResultSet rs, int rowNum) throws SQLException { ResultSetMetaData metaData = rs.getMetaData(); int columnCount = metaData.getColumnCount(); Map<String, String> rowMap = new HashMap<>(); for (int i = 1; i <= columnCount; i++) { String columnName = metaData.getColumnName(i); // 调用rs.getString()会自动将SQL类型(比如Timestamp、Integer)转为对应的字符串格式 String value = rs.getString(i); rowMap.put(columnName, value); } return rowMap; } });
这种方式的优势是完全可控,如果需要对特定字段做特殊处理(比如null值替换、格式调整),直接在循环里修改逻辑就行。
方案二:封装工具类复用逻辑
如果你的项目里经常需要这种转换,建议把上面的RowMapper封装成一个可复用的工具类:
public class StringMapRowMapper implements RowMapper<Map<String, String>> { @Override public Map<String, String> mapRow(ResultSet rs, int rowNum) throws SQLException { ResultSetMetaData metaData = rs.getMetaData(); int columnCount = metaData.getColumnCount(); Map<String, String> rowMap = new HashMap<>(); for (int i = 1; i <= columnCount; i++) { String columnName = metaData.getColumnName(i); String value = rs.getString(i); rowMap.put(columnName, value); } return rowMap; } }
之后使用就会非常简洁:
List<Map<String, String>> result = jdbcTemplate.query(sql, params, new StringMapRowMapper());
方案三:用ResultSetExtractor做底层控制
如果需要更底层的结果集处理逻辑,可以使用ResultSetExtractor:
List<Map<String, String>> result = jdbcTemplate.query(sql, params, new ResultSetExtractor<List<Map<String, String>>>() { @Override public List<Map<String, String>> extractData(ResultSet rs) throws SQLException { List<Map<String, String>> resultList = new ArrayList<>(); ResultSetMetaData metaData = rs.getMetaData(); int columnCount = metaData.getColumnCount(); while (rs.next()) { Map<String, String> rowMap = new HashMap<>(); for (int i = 1; i <= columnCount; i++) { String columnName = metaData.getColumnName(i); String value = rs.getString(i); rowMap.put(columnName, value); } resultList.add(rowMap); } return resultList; } });
为什么直接传Map<String, String>.class不行?
Java的泛型是编译时特性,编译后泛型参数会被擦除,运行时JdbcTemplate只能看到Map.class,无法感知到你想要的是Map<String, String>,所以这种写法不仅编译不通过,逻辑上也不成立。
内容的提问来源于stack exchange,提问作者membersound
相关产品推荐
相关产品推荐

