Кажется, что вывод типа не работает vavr Try работает с функцией fetchOne () в jOOQ - PullRequest
0 голосов
/ 13 декабря 2018

Я использую 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 сработал отлично, и нет никакого типа-соответствие здесь.Итак, я думаю, запрос правильно сформирован.

Затем я использую Try 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 и особенноЭто объяснение @ 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);
    }

Следуя, Лукас 'толкни, я изменил метод следующим образом:

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 Ответ

0 голосов
/ 13 декабря 2018

Учитывая код, который вы предоставили до сих пор, и предполагая, что опечаток нет, это, вероятно, вызвано вашей необработанной ссылкой на тип ResultQuery.Вместо этого используйте ResultQuery<?> или ResultQuery<Record1<Integer>>.

Никогда не используйте необработанные типы, если только вам это не нужно.И вы, вероятно, нет.

...