بادئ ذي بدء: شكرا لهذه المكتبة الرائعة! نحن نهاجر ببطء من 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;
}
})
بدلا من ذلك كل شيء يعمل بشكل جيد.
اعتقدت أن لامدا كانت مجرد سكر نحوي وأن المترجم سوف يوسع الشفرة على أي حال؟
بسبب المحو العام ، تُفقد المعلمة <CatalogueJdbi>
في وقت التشغيل ، لذلك لا يعرف Jdbi أي نوع يتم تعيينه.
هناك طريقة بديلة يمكنك استخدامها ، حيث تمرر النوع كمعامل منفصل:
.registerRowMapper(CatalogueJdbi.class, (rs, ctx) -> { ... })
هناك شيء واحد يجب ملاحظته: تسجيل مخطط الصف ثم استدعاء mapTo(type)
يضيع جهدًا إذا لم تتم إعادة استخدام مصمم الخرائط في أي مكان آخر. يمكنك فقط استدعاء طريقة map(RowMapper<T>)
وتمرير lambda مباشرةً إلى ذلك:
.map((rs, ctx) -> { ... })
كنت أعرف أنني كنت أفعل شيئًا خاطئًا :) شكرًا جزيلاً!
على سبيل المتابعة: عند إنشاء فئة داخلية مجهولة الهوية ، فأنت تقوم بإنشاء مصمم خرائط مكتوب بشكل ملموس.
ما نعنيه بالكتابة الملموسة هو أن Jdbi يمكنه الحصول على فئة مصمم الخرائط واكتشاف المعامل العام T
لـ RowMapper<T>
. سواء كنت تفعل ذلك عبر فصل دراسي كامل مثل class FooMapper implements RowMapper<Foo> { ... }
أو عبر فئة داخلية مجهولة مثل new RowMapper<Foo>() { ... }
، يبدو الأمر مشابهًا لـ Jdbi.
التعليق الأكثر فائدة
بسبب المحو العام ، تُفقد المعلمة
<CatalogueJdbi>
في وقت التشغيل ، لذلك لا يعرف Jdbi أي نوع يتم تعيينه.هناك طريقة بديلة يمكنك استخدامها ، حيث تمرر النوع كمعامل منفصل:
هناك شيء واحد يجب ملاحظته: تسجيل مخطط الصف ثم استدعاء
mapTo(type)
يضيع جهدًا إذا لم تتم إعادة استخدام مصمم الخرائط في أي مكان آخر. يمكنك فقط استدعاء طريقةmap(RowMapper<T>)
وتمرير lambda مباشرةً إلى ذلك: