Skip to content
Advertisement

Use BeanMapper from within a RowMapper?

I’m using JDBI’s SQL Objects declarative API to map an object containing a one-to-many relationship:

class Foo {
  private String id;
  private String name;
  private Set<Bar> bars = new HashSet<>();
}

class Bar {
  private String id;
}

Initially it looked like a RowReducer would be ideal:

@UseFreemarkerSqlLocator
class FooQuery {

  @SqlQuery
  @RegisterBeanMapper(value = Foo.class, prefix = "f")
  @RegisterBeanMapper(value = Bar.class, prefix = "b")
  @UseRowReducer(RowReducer.class)
  ResultIterator<Foo> queryAll();

  static class RowReducer implements LinkedHashMapRowReducer<String, Foo> {

    @Override
    public void accumulate(Map<String, Foo> map, RowView rowView) {
      final Foo foo = map.computeIfAbsent(rowView.getColumn("f_id", String.class),
          id -> rowView.getRow(Foo.class));
      if (rowView.getColumn("b_id", String.class) != null) {
        foo.addBar(rowView.getRow(Bar.class));
      }
    }
  }
}

However I soon discovered that RowReducers don’t work with ResultIterators (I’m working with a large database so it’s important to be able to stream these) so now I’m reverting back to implementing a RowMapper instead. I’d still like to use the handy BeanMappers built into JDBI though but I can’t figure out how to access them from within my RowMapper implementation.

class FooRowMapper implements RowMapper<Foo> {
  private Foo foo = null;

  @Override
  public Foo map(ResultSet rs, StatementContext ctx) throws SQLException {
    String fooId = rs.getString("f_id");
    if (foo == null || !foo.id.equals(fooId)) {
      // ideally construct using JDBI's BeanMapper similar to how we can above
      // in the RowReducer!
      foo = ??? 
    }
    // same as above...
    Bar bar = ???
    foo.addBar(bar);

    return foo;
  }
}

Is it possible to easily use BeanMappers from within a RowMapper so I don’t have to manually construct the beans?

Advertisement

Answer

RowMapper<Bar> barMapper = BeanMapper.of(Bar.class)
Bar bar = barMapper.map(rs, ctx);
foo.addBar(bar);

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement