javatuplesjdbi

How to select an aggregate query result into tuples using JDBI annotations?


I'm using JDBI and I need to run a query using aggregate functions.

How would I go about reading the result from this query? What return type can I use to make it convenient?

@SqlQuery("select count(*), location from Customers group by location")
public Type getCustomersCountByLocation();

I could possibly add an alias to the aggregate function result and write a matching POJO

@SqlQuery("select count(*) as customerCount, location from Customers group by location")
public List<CustomerLocation> getCustomersCountByLocation();

The POJO being:

public class CustomerLocation {

    private int customerCount;

    private String location;

    public CustomerLocation(int customerCount, String location) {
        this.customerCount = customerCount;
        this.location = location;
    }

    //getters
}

But that seems like a lot of unnecessary boilerplate. I could write a one-size-fits-all object for this kind of queries but that would introduce unnecessary coupling.

Does JDBI support any type OOTB that would allow me to select the result of my query into an arbitrary n-tuple parametrized with the right types?

Pseudocode:

@SqlQuery("select count(*) as customerCount, location from Customers group by location")
public List<Tuple<Integer, String>> getCustomersCountByLocation();

Solution

  • You could use Map instead. You need to write mapper once and it can be used for all aggregation queries and can be used for other use cases as well.

    @SqlQuery("select count(*) as customerCount, location from Customers group by location")
    @Mapper(MapMapper.class)
    public Map getCustomersCountByLocation();
    

    And define mapper like this.

    public class MapMapper implements ResultSetMapper<Map<String, Integer>> {
        @Override
        public Map<String, Integer> map(int index, ResultSet r, StatementContext ctx) throws SQLException {
            HashMap<String, Integer> result = new HashMap<>();
            for(int i =1; i <= r.getMetaData().getColumnCount(); i++) {
                String columnName = r.getMetaData().getColumnName(i);
                Integer value = r.getInt(i);
                result.put(columnName, value);
            }
            return result;
        }
    }