【问题标题】:what is difference between ResultSetExtractor vs Rowmapper?ResultSetExtractor 与 Rowmapper 有什么区别?
【发布时间】:2012-04-09 13:35:11
【问题描述】:

我在行映射器和结果集提取器回调接口上都工作过。我发现了不同之处,即,

1.Row mapper 可以逐行处理。但是Resultset extractor 我们可以导航所有行并且返回类型是object。

除了上面还有什么不同吗?。Rowmapper内部和返回类型是如何工作的?。

【问题讨论】:

  • 在我看来,RowMapper 要简单得多,您可能最终会使用它而不是 ResultSetExtractor。但要了解更多信息,请查看 JavaDocDocumentation

标签: spring jdbctemplate


【解决方案1】:

与 ResultsetExtractor 的基本区别在于,您需要自己遍历结果集,比如在 while 循环中。 此接口为您提供一次对整个 ResultSet 的处理。接口方法 extractData(ResultSet rs) 的实现将包含该手动迭代代码。 See one implementation of 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用于创建复杂对象

【讨论】:

  • 解释得很好。
【解决方案2】:

JavaDoc of ResultSetExtractor:

该接口主要用于JDBC框架本身。 RowMapper 通常是 ResultSet 处理的更简单选择,每行映射一个结果对象,而不是整个 ResultSet 的一个结果对象。

ResultSetExtractor 假设提取整个ResultSet(可能是多行),而RowMapper 一次只输入一行。

大多数时候,ResultSetExtractor 将循环 ResultSet 并使用 RowMapper,sn-p 示例 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;

注意,所有结果都会被转换,这会造成内存不足的异常。

另见

【讨论】:

  • ResultSetExtractor 在框架之外使用,例如,它对于使用单个 SQL 语句映射一对多非常有用,例如具有一组假期的员工。
  • 但是 RowMapper 和 ResultSetExtractor 可以用于获取记录列表??
【解决方案3】:

RowMapper: 一次处理一条ResultSet记录。

ResultSetExtractor: 一次处理多条ResultSet记录。

【讨论】:

  • 应该作为评论添加。
【解决方案4】:

我认为 ResultSetExtractor 可能具有优势的一个地方是,当您拥有一个结果集(例如来自对存储过程的调用)和一个行映射器,并且想要像在 jdbcTemplate 方法的幕后那样处理它们时, 如查询(String sql, RowMapper 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);

【讨论】:

    猜你喜欢
    • 2021-10-22
    • 1970-01-01
    • 2012-01-14
    • 1970-01-01
    • 2011-02-19
    • 2013-03-14
    • 2018-09-14
    • 2014-01-03
    • 2021-12-22
    相关资源
    最近更新 更多