Trying to build a Country object with JDBIs ResultSetMapper API, however I have one issue which I am not sure how to solve.
For a resultset like the following which joins the Regions (states/ territories) table to country (1 - 0..n)
@Override
public Country map(final int index, final ResultSet resultRow, final StatementContext ctx) throws SQLException {
final String countryIso3Code = resultRow.getString("iso3Code");
return Country.builder().name(resultRow.getString("name"))
.iso2Code(resultRow.getString("iso2Code"))
.iso3Code(resultRow.getString("iso3Code"))
.regions(....?)
.build();
}
How can I get the ResultSetMapper to initialise one Country object with the appropriate list of related Regions in JDBI
e.g.
United States - (USA) - (US) - (PR, RI, WA)
Currently the list of Countries returned is like the followng
United Kingdom - GBR - GB - <>
United States - USA - US - PR
United States - USA - US - RI
United States - USA - US - WA
Puerto Rico - PRI - PR - <>
Canada - CAN - CA - AB
Canada - CAN - CA - BC
You can use the StatementContext argument for that.
When the map method sees a new country, it creates a new Country instance and calls ctx.setAttribute to save the new instance. Later on, if there's a non-null region, it adds the region to the Country instance taken from the statement context.
Here's an example:
@Override
public Country map(final int index, final ResultSet resultRow, final StatementContext ctx) throws SQLException {
final String countryIso3Code = resultRow.getString("iso3Code");
if (countryIso3Code == null) {
throw new SQLDataException("Iso3Code is required");
}
Country country = (Country)ctx.getAttribute(countryIso3Code);
if (country == null) {
country = new Country();
country.setName(resultRow.getString("name"));
country.setIso3Code(countryIso3Code);
country.setIso2Code(resultRow.getString("iso2Code"));
ctx.setAttribute(countryIso3Code, country);
}
String region = resultRow.getString("region");
if (region != null) {
country.addRegion(region);
}
return country;
}
It's a bit inconvenient to use a builder like you do in the code you posted, but it's possible to put a builder on the statement context rather than a country.
Also, this mapper returns a country per DB row, so seven results, but since the same instance is repeated, using a Set<Country> gets you the expected four results.