0

I'm using Model Mapper with JDBI, but I'm not able to use model mapper with SQL Object Queries.

For example I have this select

@SqlQuery("select * from example")

and documentation says I have to use a ResultSetMapper or ResultSetMapperFactory to map result. I'd like to write a mapper that use model mapper, but I have some problem to understand if I can (code below doesn't work). Here is the method in the ExampleMapper class (annotation used with SqlObject is @RegisterMapper(ExampleMapper.class) )

public ExamplePO map(int index, ResultSet r, StatementContext ctx) throws SQLException{
    System.out.println("rs: " +  r.getString("id_Example"));
    ModelMapper mapper = new ModelMapper();
    mapper.getConfiguration().setSourceNameTokenizer(NameTokenizers.UNDERSCORE);
    return mapper.map(r, ExamplePO.class);
}

How can I map resultSet using model mapper? Thanks, Silvia

Silvia
  • 11
  • 5

1 Answers1

1

The problem is that the modelmapper 'map' method processes all the records in the resultset in one call, whereas the jdbi 'map' function expects the 'map' method to process a single result row at a time. The net effect is that the modelmapper greedily reads all the records in the result set the first time it is invoked. This causes the resultset to be already closed when it's passed back to modelmapper and so jdbi throws an error.

However, this is easily done in two steps, which is not quite as neat, but a lot easier than messing about with the code of either jdbi or modelmapper. The net result is what I wanted - a very very easy way to go from database to java without having to manually type in loads of field names to do the mapping.

The first step is to use the default mapper on the sql object api interface declaration which will return a List of Maps.

@SqlQuery("select product_id, title from product where product_id = :id ")
@Mapper(DefaultMapper.class)
public List<Map<String, Object>> getProductDetails(@Bind("id") long id);

ModelMapper is very happy with a list of maps, so elsewhere in your code use model mapper to convert the result to the required type. I've wrapped a real DAO around the JDBI Sql object interface for this so the jdbi interface is hidden. The conversion itself this can be done with a generic method that you can re-use for any conversion to a list of beans/pojos.

public static <T> List<T> map(Class<T> clazz, List<Map<String, Object>> data) {

    ModelMapper modelMapper = new ModelMapper();
    modelMapper.getConfiguration().setSourceNameTokenizer(NameTokenizers.UNDERSCORE);
    List<T> result = modelMapper.map(data, new TypeToken<List<T>>() {}.getType());
    return result;
}

public List<Product> getProductDetails(long id) {
    return ListMapper.map(Product.class, productDBI.getProductDetails(id));
}
Alan Brown
  • 21
  • 1
  • 3