Jdbi: 使用 lambda 时:“此处必须使用具体类型的 RowMapper”

创建于 2018-04-09  ·  3评论  ·  资料来源: jdbi/jdbi

首先:感谢这个很棒的图书馆! 我们正在慢慢地从 Hibernate 迁移到 jdbi,到目前为止对它非常满意;)

假设我有以下代码:

getHandle().createQuery("SELECT ...")
    .bind("id", id)
    .registerRowMapper((RowMapper<CatalogueJdbi>) (rs, ctx) -> {
        final CatalogueJdbi catalogue = FieldMapper.of(CatalogueJdbi.class, "c").map(rs, ctx);
        if (rs.getObject("mid") != null) {
            catalogue.setImage(FieldMapper.of(MediaFileJdbi.class, "m").map(rs, ctx));
        }

        return catalogue;
    })
    .mapTo(CatalogueJdbi.class)
    .collect(Collectors.toSet());

如图所示注册 RowMapper 时,我得到

java.lang.UnsupportedOperationException: Must use a concretely typed RowMapper here
    at org.jdbi.v3.core.mapper.InferredRowMapperFactory.lambda$new$0(InferredRowMapperFactory.java:38)
    at java.base/java.util.Optional.orElseThrow(Optional.java:385)
    at org.jdbi.v3.core.mapper.InferredRowMapperFactory.<init>(InferredRowMapperFactory.java:38)
    at org.jdbi.v3.core.mapper.RowMappers.register(RowMappers.java:63)
    at org.jdbi.v3.core.config.Configurable.lambda$registerRowMapper$16(Configurable.java:248)
    at org.jdbi.v3.core.config.Configurable.configure(Configurable.java:74)
    at org.jdbi.v3.core.config.Configurable.registerRowMapper(Configurable.java:248)
    at ...

但是当使用

.registerRowMapper(new RowMapper<CatalogueJdbi>() {
                    <strong i="13">@Override</strong>
                    public CatalogueJdbi map(final ResultSet rs, final StatementContext ctx) throws SQLException {
                        final CatalogueJdbi catalogue = FieldMapper.of(CatalogueJdbi.class, "c").map(rs, ctx);
                        if (rs.getObject("mid") != null) {
                            catalogue.setImage(FieldMapper.of(MediaFileJdbi.class, "m").map(rs, ctx));
                        }

                        return catalogue;
                    }
                })

相反,一切正常。

我认为 lambdas 只是语法糖,编译器无论如何都会扩展代码?

question

最有用的评论

由于泛型擦除, <CatalogueJdbi>参数在运行时丢失,因此 Jdbi 不知道映射器映射到什么类型。

您可以使用另一种方法,将类型作为单独的参数传递:

.registerRowMapper(CatalogueJdbi.class, (rs, ctx) -> { ... })

需要注意的一件事:注册一个行映射器然后调用mapTo(type)是浪费精力,如果该映射器没有在其他任何地方重用。 您可以调用map(RowMapper<T>)方法并将 lambda 直接传递给它:

.map((rs, ctx) -> { ... })

所有3条评论

由于泛型擦除, <CatalogueJdbi>参数在运行时丢失,因此 Jdbi 不知道映射器映射到什么类型。

您可以使用另一种方法,将类型作为单独的参数传递:

.registerRowMapper(CatalogueJdbi.class, (rs, ctx) -> { ... })

需要注意的一件事:注册一个行映射器然后调用mapTo(type)是浪费精力,如果该映射器没有在其他任何地方重用。 您可以调用map(RowMapper<T>)方法并将 lambda 直接传递给它:

.map((rs, ctx) -> { ... })

我知道我做错了 :) 非常感谢!

作为后续:当您创建匿名内部类时,您_are_ 创建了一个具体类型的映射器。

我们所说的具体类型是指 Jdbi 可以获取映射器的类并反射性地发现RowMapper<T>的泛型参数T RowMapper<T> 。 无论您是通过像class FooMapper implements RowMapper<Foo> { ... }这样的成熟类还是通过匿名内部类(例如new RowMapper<Foo>() { ... } ,对于 Jdbi 来说,它看起来都是一样的。

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

keith-miller picture keith-miller  ·  3评论

qualidafial picture qualidafial  ·  3评论

Shujito picture Shujito  ·  5评论

goxr3plus picture goxr3plus  ·  4评论

agavrilov76 picture agavrilov76  ·  5评论