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

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ć

  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

 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

    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);
    }
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.

1 użytkowników online, w tym zalogowanych: 0, gości: 1