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 in various ways depending on the type of data that I expect to obtain:
1) Query for simple type (as an int, a long or a String): I use the queryForObject() method of the jdbcTemplate class, something like it:
String sql = "SELECT count(*) FROM T_REWARD";
int rowsNumber = jdbcTemplate.queryForObject(sql, Integer.class);
So to obtain a simple object as an int value I use the queryForObject() method passing to it the sql stattment and the object type of I expect to receive in output from the method.
Ok, this is pretty simple and I think that it is ok.
2) Query for an entire table row putted into a Map object: so if I need no a single value (that could be into a single column of a specific row of a table or something like the preovious example) I can use the queryForMap(..) and the queryForList() methods, in these way:
2.1) queryForMap(): I use it if I expect a single row putted into a single Map object where each columns value is mapped into a of my Map, something like:
String sql = "select * from T_REWARD where CONFIRMATION_NUMBER = ?";
Map<String, Object> values = jdbcTemplate.queryForMap(sql,confirmation.getConfirmationNumber());
2.2) queryForList(): I use it if I expect more rows as output of my query. So I will obtain a list of Map objects where each Map object represent a specific row of the query output. Something like it:
String sql = “select * from PERSON”;
return jdbcTemplate.queryForList(sql);
I think that also this is pretty clear.
Then I can map a ResultSet into a domain object using JdbcTemplate and this is not so clear for me.
Reading the documentation is told that JdbcTemplate supports this using a callback approach. What exactly meand this callback approach ?
I know that Spring provides a RowMapper interface for mapping a single row of a ResultSet to an object:
public interface RowMapper<T> {
T mapRow(ResultSet rs, int rowNum)
throws SQLException;
}
and I have the following example compoese by this method that use a new RestaurandRowMapper object as returned object of a queryForObject() method:
public Restaurant findByMerchantNumber(String merchantNumber) {
String sql = "select MERCHANT_NUMBER, NAME, BENEFIT_PERCENTAGE, BENEFIT_AVAILABILITY_POLICY from T_RESTAURANT where MERCHANT_NUMBER = ?";
return jdbcTemplate.queryForObject(sql, new RestaurantRowMapper(), merchantNumber);
and this inner class:
class RestaurantRowMapper implements RowMapper<Restaurant> {
public Restaurant mapRow(ResultSet rs, int i) throws SQLException {
return mapRestaurant(rs);
}
}
that use this private method to create the mapping:
private Restaurant mapRestaurant(ResultSet rs) throws SQLException {
// get the row column data
String name = rs.getString("NAME");
String number = rs.getString("MERCHANT_NUMBER");
Percentage benefitPercentage = Percentage.valueOf(rs.getString("BENEFIT_PERCENTAGE"));
// map to the object
Restaurant restaurant = new Restaurant(number, name);
restaurant.setBenefitPercentage(benefitPercentage);
restaurant.setBenefitAvailabilityPolicy(mapBenefitAvailabilityPolicy(rs));
return restaurant;
}
So I have some difficulties to understand how exactly work all this stuff.
My main doubt is the following one: I know that using the queryForObject() method I pass to it, as input parameter, the type of the object that I expect as output (for example an Interger or a Long).
If I expect to obtain a domain object that represent an entire row of a table (for example a row of the Restaurant table mapped into a Restaurand object) I'm thinking that I should use this object (as the Restaurant object) but in the previous example I use the **row mapper object instead the domain object:
return jdbcTemplate.queryForObject(sql, new RestaurantRowMapper(), merchantNumber);
This inner class contain only the mapRow() method that return the expected domain object
class RestaurantRowMapper implements RowMapper<Restaurant> {
public Restaurant mapRow(ResultSet rs, int i) throws SQLException {
return mapRestaurant(rs);
}
}
So I think that Spring automatically call the mapRow() method that return the Restaurand domain object that is automatically replaced into the queryForObject() method, or something like this. But I am not so sure about it exactly work.
What am I missing? Can you explain me what exactly happen in the backstage?
Tnx