问题描述
有人可以告诉我以下示例代码中的问题是什么。 为了举例说明,我们可以假设resultSet中所有列均可用,并且所有内容均为String。
下面代码中的最后一行失败。
ResultSet rs = JdbcTemplate.query(......)
List<String> columnName= <some predefined fixed values> ;
Map<String,String> columnAndValueMap
= columnName
.stream()
.collect(Collectors.toMap(
Function.identity(),rs::getString)); //Cannot resolve method 'getString'
解决方法
Collectors.toMap
期望Function<String,String>
作为第二个参数(值映射器函数)。
Function<String,String>
是具有以下单个抽象方法的功能接口:
String apply(String arg);
但是,ResultSet.getString
方法具有以下签名:
String getString(String columnLabel) throws SQLException;
由于SQLException
是一个已检查的异常,因此它使ResultSet.getString
方法与Function.apply
方法不兼容,因此会出现该错误。
如@vphilipnyc在their answer中所示,您可以将for
循环与try/catch
块一起使用来处理您的情况。或者,如果您想坚持使用更具功能性的方法,则可以声明自己的功能接口,该接口将SQLException
的引发函数调整为通用的java.util.function.Function
(通过继承):
@FunctionalInterface
public interface SQLFunction<T,R> extends Function<T,R> {
R applySQL(T t) throws SQLException;
@Override
default R apply(T t) {
try {
return applySQL(t);
} catch (SQLException e) {
throw new RuntimeException(e); // or your own unchecked exception
}
}
static <T,R> Function<T,R> adapt(SQLFunction<T,R> f) {
return f;
}
}
然后,您可以通过以下方式使用它:
Map<String,String> columnAndValueMap = columnName.stream()
.collect(Collectors.toMap(
Function.identity(),SQLFunction.adapt(rs::getString)));
,
正如@fps所提到的,rs.getString()
方法会按照其签名中所述抛出SQLException。
假设您要创建一个以列名作为键,结果集字符串作为值的映射,则可以执行以下操作:
List<String> columnNames = List.of("columnA","columnB");
Map<String,Object> map = columnNames.stream().collect(
Collectors.toMap(Function.identity(),s -> {
try {
return Optional.ofNullable(rs.getString(s));
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return s;
}));
这有点混乱,因为您需要在流操作期间捕获SQLException
。此外,由于Optional
方法可以返回null,因此鼓励使用getString()
。 (了解到您假设不会有null。您的IDE可能会突出显示缺少Optional
作为警告。)
相反,使用简单的for循环并用try / catch包围起来可能会更好:
Map<String,String> map = new HashMap<>(columnNames.size());
for (String columnName : columnNames) {
try {
map.put(columnName,rs.getString(columnName));
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}