I am studying for the Spring Core certification and I have some doubts about how Spring handle the JDBC queries:
So I know that I can obtain data from my DB tables i
The queryForObject method looks like this:
public T queryForObject(String sql, RowMapper rowMapper, Object... args) throws DataAccessException {
List results = query(sql, args, new RowMapperResultSetExtractor(rowMapper, 1));
return DataAccessUtils.requiredSingleResult(results);
}
The queryForObject-method internally invokes the method query on the JdbcTemplate object. The query-method is defined as:
public T query(
PreparedStatementCreator psc, final PreparedStatementSetter pss, final ResultSetExtractor rse)
throws DataAccessException;
As you can see, a ResultSetExtractor is passed to the query-method and Spring conveniently converts your RowMapper to an object of type new RowMapperResultSetExtractor. The RowMapperResultSetExtractor is the object that holds the key to the magic. When the object is invoked it iterates all rows as per this snippet:
public List extractData(ResultSet rs) throws SQLException {
List results = (this.rowsExpected > 0 ? new ArrayList(this.rowsExpected) : new ArrayList());
int rowNum = 0;
while (rs.next()) {
results.add(this.rowMapper.mapRow(rs, rowNum++));
}
return results;
}
So, your original RowMapper is the callback that is called for each row. Furthermore, as you can see here your RowMapper is invoked for all matching results and the Restaurant-object that you created is added to the result list. However, since you query for only one object the following statement is finally used to return your single Restaurant object.
return DataAccessUtils.requiredSingleResult(results);
So, to sum up: JdbcTempalte implementes the Strategy Pattern (which is similar to the Template method pattern). And by providing a Strategy interface (the RowMapper) you can let JdbcTemplate do the heavy lifting for you (handling exceptions, connections etc). The RowMapper maps each hit as a POJO (the Restaurant) and all hits are collected to a List. The method queryForObject then takes the first row from that List and returns it to the caller. The return value is based on the generic type of the RowMapper which in your case is Restaurant.