@Override void configureReturner(Query q, SqlObjectStatementConfiguration cfg) { UseRowMapper useRowMapper = getMethod().getAnnotation(UseRowMapper.class); UseRowReducer useRowReducer = getMethod().getAnnotation(UseRowReducer.class); if (useRowReducer != null && useRowMapper != null) { throw new IllegalStateException("Cannot declare @UseRowMapper and @UseRowReducer on the same method."); } cfg.setReturner(() -> { StatementContext ctx = q.getContext(); QualifiedType<?> elementType = magic.elementType(ctx); if (useRowReducer != null) { return magic.reducedResult(q.reduceRows(rowReducerFor(useRowReducer)), ctx); } ResultIterable<?> iterable = useRowMapper == null ? q.mapTo(elementType) : q.map(rowMapperFor(useRowMapper)); return magic.mappedResult(iterable, ctx); }); }
@RegisterFieldMapper(value = Article.class, prefix = "a") @RegisterFieldMapper(value = Comment.class, prefix = "c") default Optional<Article> getArticleWithComments(long id) { return getHandle().select( "select " + " a.id a_id, " + " a.title a_title, " + " a.content a_content, " + " c.id c_id, " + " c.content c_content " + "from articles a " + "left join comments c " + " on a.id = c.article_id " + "where a.id = ? " + "order by c.id", id) .reduceRows(Optional.empty(), (acc, rv) -> { Article a = acc.orElseGet(() -> rv.getRow(Article.class)); if (rv.getColumn("c_id", Long.class) != null) { a.getComments().add(rv.getRow(Comment.class)); } return Optional.of(a); }); } }
@RegisterConstructorMapper(value = Article.class, prefix = "a") @RegisterConstructorMapper(value = Comment.class, prefix = "c") default Optional<Article> getArticleWithComments(long id) { return getHandle().select( "select " + " a.id a_id, " + " a.title a_title, " + " a.content a_content, " + " c.id c_id, " + " c.content c_content " + "from articles a " + "left join comments c " + " on a.id = c.article_id " + "where a.id = ? " + "order by c.id", id) .reduceRows(Optional.empty(), (acc, rv) -> { Article a = acc.orElseGet(() -> rv.getRow(Article.class)); if (rv.getColumn("c_id", Long.class) != null) { a.getComments().add(rv.getRow(Comment.class)); } return Optional.of(a); }); } }
@RegisterBeanMapper(value = Article.class, prefix = "a") @RegisterBeanMapper(value = Comment.class, prefix = "c") default Optional<Article> getArticleWithComments(long id) { return getHandle().select( "select " + " a.id a_id, " + " a.title a_title, " + " a.content a_content, " + " c.id c_id, " + " c.content c_content " + "from articles a " + "left join comments c " + " on a.id = c.article_id " + "where a.id = ? " + "order by c.id", id) .reduceRows(Optional.empty(), (acc, rv) -> { Article a = acc.orElseGet(() -> rv.getRow(Article.class)); if (rv.getColumn("c_id", Long.class) != null) { a.getComments().add(rv.getRow(Comment.class)); } return Optional.of(a); }); } }
@Test public void testReduceRows() { List<SomethingWithLocations> result = dbRule.getSharedHandle() .createQuery("SELECT something.id, name, location FROM something NATURAL JOIN something_location") .reduceRows((Map<Integer, SomethingWithLocations> map, RowView rv) -> map.computeIfAbsent(rv.getColumn("id", Integer.class), id -> new SomethingWithLocations(rv.getRow(Something.class))) .locations .add(rv.getColumn("location", String.class))) .collect(toList()); assertThat(result).containsExactly( new SomethingWithLocations(new Something(1, "tree")).at("outside"), new SomethingWithLocations(new Something(2, "apple")).at("tree").at("pie")); }
@Test public void testReduceRowsWithSeed() { Map<Integer, SomethingWithLocations> result = dbRule.getSharedHandle() .createQuery("SELECT something.id, name, location FROM something NATURAL JOIN something_location") .reduceRows(new HashMap<Integer, SomethingWithLocations>(), (map, rr) -> { map.computeIfAbsent(rr.getColumn("id", Integer.class), id -> new SomethingWithLocations(rr.getRow(Something.class))) .locations .add(rr.getColumn("location", String.class)); return map; }); assertThat(result).hasSize(2) .containsEntry(1, new SomethingWithLocations(new Something(1, "tree")).at("outside")) .containsEntry(2, new SomethingWithLocations(new Something(2, "apple")).at("tree").at("pie")); }
@RegisterBeanMapper(value = Article.class, prefix = "a") @RegisterBeanMapper(value = Comment.class, prefix = "c") default Optional<Article> getArticleWithComments(long id) { return getHandle().select( "select " + " a.id a_id, " + " a.title a_title, " + " a.content a_content, " + " c.id c_id, " + " c.content c_content " + "from articles a " + "left join comments c " + " on a.id = c.article_id " + "where a.id = ? " + "order by c.id", id) .reduceRows(Optional.empty(), (acc, rv) -> { Article a = acc.orElseGet(() -> rv.getRow(Article.class)); if (rv.getColumn("c_id", Long.class) != null) { a.getComments().add(rv.getRow(Comment.class)); } return Optional.of(a); }); } }
@RegisterFieldMapper(value = Article.class, prefix = "a") @RegisterFieldMapper(value = Comment.class, prefix = "c") default Optional<Article> getArticleWithComments(long id) { return getHandle().select( "select " + " a.id a_id, " + " a.title a_title, " + " a.content a_content, " + " c.id c_id, " + " c.content c_content " + "from articles a " + "left join comments c " + " on a.id = c.article_id " + "where a.id = ? " + "order by c.id", id) .reduceRows(Optional.empty(), (acc, rv) -> { Article a = acc.orElseGet(() -> rv.getRow(Article.class)); if (rv.getColumn("c_id", Long.class) != null) { a.getComments().add(rv.getRow(Comment.class)); } return Optional.of(a); }); } }
@RegisterConstructorMapper(value = Article.class, prefix = "a") @RegisterConstructorMapper(value = Comment.class, prefix = "c") default Optional<Article> getArticleWithComments(long id) { return getHandle().select( "select " + " a.id a_id, " + " a.title a_title, " + " a.content a_content, " + " c.id c_id, " + " c.content c_content " + "from articles a " + "left join comments c " + " on a.id = c.article_id " + "where a.id = ? " + "order by c.id", id) .reduceRows(Optional.empty(), (acc, rv) -> { Article a = acc.orElseGet(() -> rv.getRow(Article.class)); if (rv.getColumn("c_id", Long.class) != null) { a.getComments().add(rv.getRow(Comment.class)); } return Optional.of(a); }); } }