我在行映射器和结果集提取器回调接口上都工作过。我发现了不同之处,即,
1.Row mapper 可以逐行处理。但是Resultset 提取器我们可以导航所有行并且返回类型是对象。
除了上面还有什么不同吗?。Rowmapper 内部的工作原理和返回类型是列表吗?。
我在行映射器和结果集提取器回调接口上都工作过。我发现了不同之处,即,
1.Row mapper 可以逐行处理。但是Resultset 提取器我们可以导航所有行并且返回类型是对象。
除了上面还有什么不同吗?。Rowmapper 内部的工作原理和返回类型是列表吗?。
基本区别在于ResultsetExtractor,您需要自己遍历结果集,比如在while循环中。此接口为您提供一次对整个 ResultSet 的处理。接口方法 extractData(ResultSet rs) 的实现将包含该手动迭代代码。 查看ResultsetExtractor的一种实现
而像 RowCallbackHandler 这样的回调处理程序,接口方法 processRow(ResultSet rs) 会为您循环。
RowMapper 既可以用于映射每一行,也可以用于映射整行。
对于整行对象(通过模板方法 jdbcTemplate.query())
public List findAll() {
String sql = "SELECT * FROM EMPLOYEE";
return jdbcTemplate.query(sql, new EmployeeRowMapper());
}
without casting will work
对于单个对象(使用模板方法 jdbcTemplate.queryForObject())
@SuppressWarnings({ "unchecked", "rawtypes" })
public Employee findById(int id) {
String sql = "SELECT * FROM EMPLOYEE WHERE ID = ?";
// jdbcTemplate = new JdbcTemplate(dataSource);
Employee employee = (Employee) jdbcTemplate.queryForObject(sql, new EmployeeRowMapper(), id );
// Method 2 very easy
// Employee employee = (Employee) jdbcTemplate.queryForObject(sql, new Object[] { id }, new BeanPropertyRowMapper(Employee.class));
return employee;
}
@SuppressWarnings("rawtypes")
public class EmployeeRowMapper implements RowMapper {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
Employee employee = new Employee();
employee.setId(rs.getInt("ID"));
employee.setName(rs.getString("NAME"));
employee.setAge(rs.getInt("AGE"));
return employee;
}
}
最佳用例:
Row Mapper:当一个ResultSet的每一行都映射到一个域Object时,可以实现为私有内部类。
RowCallbackHandler:当没有从每一行的回调方法返回值时,例如将行写入文件,将行转换为 XML,在添加到集合之前过滤行。非常有效,因为这里没有完成 ResultSet 到 Object 的映射。
ResultSetExtractor:当多行 ResultSet 映射到单个 Object 时。就像在查询中进行复杂连接时,可能需要访问整个 ResultSet 而不是单行 rs 来构建复杂的 Object,并且您希望完全控制 ResultSet。就像将从 TABLE1 和 TABLE2 的连接返回的行映射到完全重构的 TABLE 聚合。
ParameterizedRowMapper用于创建复杂对象
该接口主要用于 JDBC 框架本身。RowMapper 通常是 ResultSet 处理的一种更简单的选择,每行映射一个结果对象,而不是为整个 ResultSet 映射一个结果对象。
ResultSetExtractor
假设提取整个ResultSet
(可能是多行),同时RowMapper
一次输入一行。
大多数时候,ResultSetExtractor
将循环ResultSet
使用RowMapper
Spring 的代码片段示例RowMapperResultSetExtractor
:
List<T> results = (this.rowsExpected > 0 ? new ArrayList<T>(this.rowsExpected) : new ArrayList<T>());
int rowNum = 0;
while (rs.next()) {
results.add(this.rowMapper.mapRow(rs, rowNum++));
}
return results;
注意,所有结果都会被转换,这会产生 Out Of Memory 异常。
RowMapper
:一次处理一条ResultSet记录。
ResultSetExtractor
:一次处理多条ResultSet记录。
我认为 ResultSetExtractor 可能具有优势的一个地方是,当您拥有一个结果集(例如从调用存储过程)和一个行映射器,并且想要像在 jdbcTemplate 方法的幕后那样处理它们时,例如查询(字符串 sql,RowMapper 行映射器)。在这种情况下,您可以通过使用 ResultSetExtractor 而不仅仅是 RowMapper 来手动迭代结果集。
例如:
行映射器
ResultSet resultSet = cs.executeQuery();
int row = 0;
DateRowMapper dateRowMapper = new DateRowMapper();
List<String> dates = new ArrayList<>();
while (resultSet.next()) {
dates.add(dateRowMapper.mapRow(resultSet, ++row));
}
return dates;
结果集提取器
ResultSet resultSet = callableStatement.executeQuery();
return new RowMapperResultSetExtractor<>(new DateRowMapper()).extractData(resultSet);