首先:感谢这个很棒的图书馆! 我们正在慢慢地从 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 只是语法糖,编译器无论如何都会扩展代码?
由于泛型擦除, <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 来说,它看起来都是一样的。
最有用的评论
由于泛型擦除,
<CatalogueJdbi>
参数在运行时丢失,因此 Jdbi 不知道映射器映射到什么类型。您可以使用另一种方法,将类型作为单独的参数传递:
需要注意的一件事:注册一个行映射器然后调用
mapTo(type)
是浪费精力,如果该映射器没有在其他任何地方重用。 您可以调用map(RowMapper<T>)
方法并将 lambda 直接传递给它: