java - 类型推断似乎失败 vavr 的 Try 适用于 jOOQ 的 fetchOne() 函数
问题描述
我正在使用 vavr 和 jOOQ,这是最近出现的两个很棒的库,允许我们在常规 Java 服务器应用程序中使用函数式方言。
我正在尝试使用 jOOQ,它相当于 SQL 的 select count (*)。
查询是这样形成的:
ResultQuery query = dsl.selectCount()
.from(Tables.SH_PLAYER_REPORT)
.join(Tables.SH_PLAYERS)
.on(Tables.SH_PLAYERS.PLAYER_ID.eq(Tables.SH_PLAYER_REPORT.PLAYER_ID))
.join(Tables.SH_LOCATION)
.on(Tables.SH_LOCATION.LOCATION_ID.eq(Tables.SH_PLAYERS.LOCATION))
.and(Tables.SH_PLAYER_REPORT.START_ON.ge(Timestamp.from(fromWhenInUTCInstant)))
.and(Tables.SH_PLAYER_REPORT.START_ON.le(Timestamp.from(toWhenInUTCInstant)))
.and(Tables.SH_LOCATION.LOCATION_ID.eq(criteriaAllFieldsTeam.getLocation_id()));
jOOQ 的生成器运行良好,这里没有任何类型不匹配。所以,我想,查询是正确形成的。
然后,我正在使用 vavr 的 Try,因此:
Optional<Integer> mayBeCount = Optional.empty();
try (final Connection cn = this.ds.getConnection()) {
DSLContext dsl = DSL.using(cn, this.dialect);
Try<Integer> countFromDBAttempted =
Try
.of(() -> prepareCountOfGamesPlayedQuery(dsl,criteriaAllFieldsTeam))
.map(e -> e.fetchOne(0, Integer.class)) // Here's the problem!
.onFailure(e -> logger.warning(String.format("Count Of Games Played, status=Failed, reason={%s}",e.getMessage())));
mayBeCount = (countFromDBAttempted.isFailure() ? Optional.empty() : Optional.of(countFromDBAttempted.getOrElse(0)));
} catch (SQLException ex) {
logger.warning(
String.format("DB(jOOQ): Failed, counting games played, using criteria {%s},reason={%s}",criteriaAllFieldsTeam.toString(),ex.getMessage()));
}
return (mayBeCount);
尽管我提供了帮助,但编译器无法通过描述目标类型来推断字段的类型:Integer.class!
../ReportByTeamRecordProducerImpl.java:66: error: incompatible types: Try<Object> cannot be converted to Try<Integer>
.onFailure(e -> logger.warning(String.format("Count Of Games Played, status=Failed, reason={%s}",e.getMessage())));
^
不出所料,当我强制输入类型时,代码运行得非常好。我只是在编译器认为.. er .. 令人反感的那一行引入了显式转换!
Try<Integer> countFromDBAttempted =
Try
// The following function returns the ResultQuery shown above
.of(() -> prepareCountOfGamesPlayedQuery(dsl,criteriaAllFieldsTeam))
// Casting below, because of some incompatibility between vavr and jOOQ
.map(e -> ((Integer) e.fetchOne(0, Integer.class)))
.onFailure(e -> logger.warning(String.format("Count Of Games Played, status=Failed, reason={%s}",e.getMessage())));
根据我对 jOOQ 库的理解,尤其是 @LukasEder 的解释,我尝试了其他几种方法。
到目前为止,我还没有尝试过引入Converter,因为对于单个字段值,这在我看来似乎是不必要的!但是,如果是这样的话,那么我想有一个提示。
回应@LukasEder:
private ResultQuery prepareCountOfGamesPlayedQuery(DSLContext dsl, CriteriaAllFieldsTeam criteriaAllFieldsTeam) {
Instant fromWhenInUTCInstant =
convertToDBCompatibleInstantUTC(
criteriaAllFieldsTeam.getDate_range().getFromWhen(),
criteriaAllFieldsTeam.getDate_range().getInTimeZone());
Instant toWhenInUTCInstant =
convertToDBCompatibleInstantUTC(
criteriaAllFieldsTeam.getDate_range().getToWhen(),
criteriaAllFieldsTeam.getDate_range().getInTimeZone());
ResultQuery query = dsl.selectCount()
.from(Tables.SH_PLAYER_REPORT)
.join(Tables.SH_PLAYERS)
.on(Tables.SH_PLAYERS.PLAYER_ID.eq(Tables.SH_PLAYER_REPORT.PLAYER_ID))
.join(Tables.SH_LOCATION)
.on(Tables.SH_LOCATION.LOCATION_ID.eq(Tables.SH_PLAYERS.LOCATION))
.and(Tables.SH_PLAYER_REPORT.START_ON.ge(Timestamp.from(fromWhenInUTCInstant)))
.and(Tables.SH_PLAYER_REPORT.START_ON.le(Timestamp.from(toWhenInUTCInstant)))
.and(Tables.SH_LOCATION.LOCATION_ID.eq(criteriaAllFieldsTeam.getLocation_id()));
return (query);
}
在 Lukas 的推动下,我以这种方式修改了该方法:
private ResultQuery<Record1<Integer>> prepareCountOfGamesPlayedQuery(DSLContext dsl, CriteriaAllFieldsTeam criteriaAllFieldsTeam) {
Instant fromWhenInUTCInstant =
convertToDBCompatibleInstantUTC(
criteriaAllFieldsTeam.getDate_range().getFromWhen(),
criteriaAllFieldsTeam.getDate_range().getInTimeZone());
Instant toWhenInUTCInstant =
convertToDBCompatibleInstantUTC(
criteriaAllFieldsTeam.getDate_range().getToWhen(),
criteriaAllFieldsTeam.getDate_range().getInTimeZone());
ResultQuery<Record1<Integer>> query = dsl.selectCount()
.from(Tables.SH_PLAYER_REPORT)
.join(Tables.SH_PLAYERS)
.on(Tables.SH_PLAYERS.PLAYER_ID.eq(Tables.SH_PLAYER_REPORT.PLAYER_ID))
.join(Tables.SH_LOCATION)
.on(Tables.SH_LOCATION.LOCATION_ID.eq(Tables.SH_PLAYERS.LOCATION))
.and(Tables.SH_PLAYER_REPORT.START_ON.ge(Timestamp.from(fromWhenInUTCInstant)))
.and(Tables.SH_PLAYER_REPORT.START_ON.le(Timestamp.from(toWhenInUTCInstant)))
.and(Tables.SH_LOCATION.LOCATION_ID.eq(criteriaAllFieldsTeam.getLocation_id()));
return (query);
}
..而且,现在和平再次在世界上盛行!
谢谢,卢卡斯!
解决方案
鉴于您到目前为止提供的代码,并假设没有拼写错误,这可能是由于您对ResultQuery
. 使用ResultQuery<?>
或ResultQuery<Record1<Integer>>
代替。
永远不要使用原始类型,除非你真的必须这样做。而你可能不会。
推荐阅读
- sql - 如何创建在数据库中具有只读访问权限但对数据库中的模式具有所有权限的用户?
- node.js - 使用 Twilio API 发送大量文本
- javascript - 如何从 TextBox 中获取文本并将其放在 HTML 中的锚标记中
- spring-boot - 如何忽略 logback RollingFileAppender FileNotFoundException
- javascript - 文本框值 onchange 添加新列
- .net-core - 寻找 dotnetcore 规格
- python - 如何将我抓取的数据保存在 AWS s3 存储桶中
- terraform - Terraform - 基于资源计数查询创建列表未返回结果
- python - 在 Pyspark 中计算滚动百分位数
- python - 这个 RE 匹配什么?