Optional ifPresent wykonuje zarówno operację w map jak i orElse

Optional ifPresent wykonuje zarówno operację w map jak i orElse
AP
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 165
0

Mam taką metodę, która ma strzelić do repozytorium, które zwraca Optional'a z jakąś wartością i
-jeżeli ta wartość istnieje, chcę do niej coś dodać
-jeżeli ta wartość nie istnieje, chcę ją stworzyć

Kopiuj
  Either<Error, DailyConsumption> addProductToDailyConsumption(UpdateDailyConsumptionDto dailyDto) {
        return repository.getDailyConsumption(dailyDto.getUsername(), dailyDto.getDate())
                .map(daily -> addToDaily(daily, dailyDto.getProduct()))
                .orElse(createNewDaily(dailyDto));
    }

Problem w tym, że to nie działa tak jak chce. Podczas testów, przy pierwszym wywołaniu tej usługi faktycznie tworzony jest nowy wpis na bazie, ale przy drugim strzale wykonują się operacje zarówno z map jaki z orElse, czyli poprzedni obiekt jest aktualizowany, ale tworzony też jest nowy... Niżej zamieszczam resztę implementacji tego serwisu. Dodam tylko, że zmiana powyższego kodu na isPresent()/get() powoduje że wszystko działa ok

Kopiuj
 var daily = repository.getDailyConsumption(dailyDto.getUsername(), dailyDto.getDate());
 if(daily.isPresent()) {
     return addToDaily(daily.get(), dailyDto.getProduct());
 } else {
      return createNewDaily(dailyDto);
}

A tutaj wspomniana reszta implementacji

Kopiuj
    private Either<Error, DailyConsumption> createNewDaily(UpdateDailyConsumptionDto dailyDto) {
        log.info("Creating new daily");
        return Try.of(() -> create(dailyDto))
                .onFailure(e -> log.severe(e.getMessage()))
                .toEither(DietError.PERSISTENCE_FAILED);
    }

    private Either<Error, DailyConsumption> addToDaily(DailyConsumption daily, ConsumedProduct product) {
        log.info("Adding to existing daily");
        return Try.of(() -> add(daily, product))
                .onFailure(e -> log.severe(e.getMessage()))
                .toEither(DietError.PERSISTENCE_FAILED);
    }

    private DailyConsumption create(UpdateDailyConsumptionDto dailyDto) {
        var daily = DailyConsumption.builder()
                .username(dailyDto.getUsername())
                .date(dailyDto.getDate())
                .consumedProducts(List.of(dailyDto.getProduct()))
                .build();
        return repository.updateDailyConsumption(daily);
    }

    private DailyConsumption add(DailyConsumption daily, ConsumedProduct consumedProduct) {
        daily.getConsumedProducts().add(consumedProduct);
        return repository.updateDailyConsumption(daily);
    }
Shalom
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Space: the final frontier
  • Postów: 26433
5

orElseGet + Supplier do tej nowej wartości -> .orElseGet(()->createNewDaily(dailyDto));
Sam orElse się ewaluuje od razu niezależnie od tego który przypadek się wykona, tylko samo przypisanie zależy od tego czy optional był pusty czy nie. Ale obie wartości są obliczane.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.