编程语言
首页 > 编程语言> > java – 类型推断似乎失败vavr的尝试适用于jOOQ的fetchOne()函数

java – 类型推断似乎失败vavr的尝试适用于jOOQ的fetchOne()函数

作者:互联网

我正在使用vavr和jOOQ,最近出现了两个出色的库,允许我们在常规Java服务器应用程序中使用功能方言.

我试图使用jOOQ,相当于SQL的选择计数(*).

查询以这种方式形成:

 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的尝试,因此:

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())));
                         ^

不出所料,当我强制进行类型化时,代码运行得非常好.我只是介绍一个显式的强制转换,在编译器认为的行…呃..令人反感!

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库的理解,特别是@ LukasEderexplanation,我尝试了其他几种方法.

我到目前为止还没有尝试过,是介绍一个转换器,因为对于单个字段值,这对我来说似乎是不必要的!但是,如果就是这样,那么我想提一下.

回应@ 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>>代替.

除非你真的需要,否则不要使用原始类型.你可能没有.

标签:java,mysql,jooq,vavr
来源: https://codeday.me/bug/20190527/1161567.html