Reputation: 1111
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 RowReducer
s don't work with ResultIterator
s (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 BeanMapper
s 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?
Upvotes: 2
Views: 903
Reputation: 198
RowMapper<Bar> barMapper = BeanMapper.of(Bar.class)
Bar bar = barMapper.map(rs, ctx);
foo.addBar(bar);
Upvotes: 2