java类型推断似乎失败了vavr对jOOQ的fetchOne()函数的尝试
我正在使用vavr和jOOQ,这是最近推出的两个很棒的库,允许我们在常规Java服务器应用程序中使用函数方言
我正在尝试使用jOOQ获取数据,它相当于SQL的selectcount(*)
查询的形成方式如下:
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推断字段的类型,尽管我给了它帮助。类
../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())));
^
毫不奇怪,当我强制类型时,代码运行得非常好。我只是在编译器考虑的行中引入一个显式强制转换。。呃。。讨厌
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库的理解,特别是对这个explanationby LukasEder的理解,我尝试了其他几种方法
到目前为止,我还没有尝试过引入一个转换器,因为对于单个字段值,在我看来这似乎是不必要的!然而,如果是这样的话,那么我想得到一个提示
针对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);
}
。。现在,和平再次在世界上盛行
谢谢你,卢卡斯
# 1 楼答案
考虑到目前为止您提供的代码,并且假设没有输入错误,这可能是由于您对^{} 的原始类型引用造成的。用
ResultQuery<?>
或ResultQuery<Record1<Integer>>
代替永远不要使用原始类型,除非你真的需要。而你可能没有