Я использую декларативный API SQL Objects JDBI для сопоставления объекта, содержащего отношение один-ко-многим:
class Foo {
private String id;
private String name;
private Set<Bar> bars = new HashSet<>();
}
class Bar {
private String id;
}
Изначально это выглядело как RowReducer
, было бы идеально:
@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));
}
}
}
}
Однако вскоре я обнаружил, что RowReducer
s не работают с ResultIterator
s (я работаю с большой базой данных, поэтому важно иметь возможность передавать их в потоковом режиме), так что теперь я возвращаюсь вернуться к реализации RowMapper
вместо. Я все еще хотел бы использовать удобные BeanMapper
, встроенные в JDBI, но я не могу понять, как получить к ним доступ из моей реализации RowMapper
.
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;
}
}
Возможно ли легко использовать BeanMappers из RowMapper, поэтому мне не нужно вручную создавать bean-компоненты?