Cześć,
Stosując funkcję java .map()
z klasy Stream z biblioteki VAVR i wykorzystując JPA i Hibernatowe dirty-checking, updatujemy rekord, natomiast updatuje się tylko raz, bo tylko raz wchodzi do metody, mimo, że lista, po której streamujemy ma 2 elementy. Kod źródłowy poniżej:
@RequiredArgsConstructor
class AgreementService {
private final AgreementFacade agreementFacade;
private final UserFinderFacade userFinderFacade;
private final UserFacade userFacade;
AddressEntity create(AddressEntity addressEntity) {
return Option.of(addressEntity)
.map(this::createAgreement)
.map(Agreement::getId)
.map(agreement -> updateUsers(agreement, addressEntity)
.map(agreementId -> deleteOldAgreement(addressEntity, agreementId))
.getOrElseThrow(UnexpectedException::new);
}
private Agreement createAgreement(AddressEntity addressEntity) {
return Option.of(addressEntity.getId())
.map(Agreement::restore)
.map(agreementFacade::save)
.getOrElseThrow(UnexpectedException::new);
}
private long updateUsers(long newAgreementId, AddressEntity addressEntity) {
return Option.of(addressEntity)
.map(AddressEntity::getId)
.flatMap(id -> agreementFacade.findByAddressIdAndAgreementStatus(id, AgreementStatus.REOPENED))
.transform(
agreement -> agreement
.map(Agreement::getId)
.map(userFinderFacade::findUsersByAgreementId)
.getOrElse(List::empty)
.toStream()
.map(user -> userFacade.assignAgreement(user.getId(), newAgreementId))
.transform(__ -> agreement.get().getId())
);
}
private AgreementEntity deleteOldAgreement(AddressEntity foundAddress, Long agreementId) {
agreementFacade.deleteByAgreementId(agreementId);
return foundAddress;
}
}
Natomiast kod metody userFacade.assignAgreement()
wygląda tak:ś
private UserDto assignAgreement(final long userId, final long agreementId) {
return userRepository.findById(userId)
.map(user -> user.agreementId(agreementId))
.map(userMapper::map)
.getOrElseThrow(UnexpectedException::new);
}
Problem jest w tym, że w linijce, gdzie szukamy agreement
metodą userFinderFacade::findUsersByAgreementId)
, zwraca 2 elementy, dalej metoda .toStream()
ma także 2 elementy, natomiast po wywołaniu tej metody, userFacade.assignAgreement()
wywołuje się tylko raz. Po zamianie tych metod na te z java.util
to wygląda tak samo. Po przerobieniu tego kodu tak, żeby zamiast metody .map()
zastosować .forEach()
, metoda ta wykonuje się 2 razy. Czy moglibyście pomóc? Stawiałem gdzieś na transakcje może, ale to raczej nie to. Na encjach mamy także @DynamicInsert
i @DynamicUpdate
, ale to chyba też nie powinno mieć wpływu? Z góry dzięki za pomoc
99xmarcin::
->
(
)
Zakładam że debugowanie tego jest równie przyjemne co czytanie....99xmarcin.transform(__ -> agree
to nie najlepszy pomysł. Spróbuj wcześniej zmaterializować stream (skonwertuj do array'a lub List'a).toStream()
getOrElseThrow
.99xmarcin