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> T queryForObject(String sql, RowMapper<T> rowMapper, Object... args) throws DataAccessException {
List<T> results = query(sql, args, new RowMapperResultSetExtractor<T>(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> T query(
PreparedStatementCreator psc, final PreparedStatementSetter pss, final ResultSetExtractor<T> rse)
throws DataAccessException;
As you can see, a ResultSetExtractor<T>
is passed to the query
-method and Spring conveniently converts your RowMapper<T>
to an object of type new RowMapperResultSetExtractor<T>(rowMapper, 1)
. 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<T> extractData(ResultSet rs) throws SQLException {
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;
}
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
.
Use jdbcTemplate.queryForObject it will resolve your problem like this
public YourPojo getDatabaseDetails(int masterId) {
sql = "Select * FROM <table_name> where ID=?";
YourPojo pojo = (YourPojo) jdbcTemplate.queryForObject(sql,
new Object[] { masterId }, new RowMapper<YourPojo>() {
@Override
public <YourPojo> mapRow(ResultSet rs, int rowNum)
throws SQLException {
YourPojo pojo2 = new YourPojo();
pojo2.setAccountId(rs.getString("AccountId"));
pojo2.setAccountName(rs.getString("AccountName"));
pojo2.setAccountCRN(rs.getString("AccountCRN"));
pojo2.setAccountStatus(rs.getString("AccountStatus"));
return pojo2;
}
});
return pojo;
}