Aktywne Wpisy
![Jo_chca](https://wykop.pl/cdn/c0834752/d438bb3c57cfc43aa10d8eaf877f7af92cc0e1f8ce00a7fc54d40922c02885e5,q60.jpg)
Jo_chca +1119
Treść przeznaczona dla osób powyżej 18 roku życia...
![robert5502](https://wykop.pl/cdn/c0834752/32a632e8e0a3ffb60db50c3b3d3523343c92d427616d5121dd2549a029ee9601,q60.jpg)
robert5502 +413
Treść przeznaczona dla osób powyżej 18 roku życia...
Skopiuj link
Skopiuj linkWykop.pl
- istnieje encja Osoba ( imie, drugieImie, plec, dataChrztu )
- istnieje punkt końcowy "update" pozwalający zaktualizować encję
- przekazujemy tylko te własności, jakie chcemy zmienić
- na przykład
{"imie":"Jacek","drugie_imie":null}
- osoby zapisujemy do bazy Mongo
Czyli istnieje sobie klasa:
java
@Data
class Osoba {
private String imie;
private String drugieImie;
private Plec plec;
private LocalDate dataChrztu;
}
Istnieje już jedna encja w Mongo:
json
{"imie":"Adam","drugie_imie":"Alan","plec":"M","dataChrztu":"2000-01-01"}
Teraz przychodzi update - chcemy zaktualizować tylko te 2 konkretne pola:
json
{"imie":"Jacek","drugie_imie":null}
Czyli zmiana imienia na Jacek i usunięcie drugiego imienia.
Wszystko fajnie, jeśli operujemy na mapach / tablicach asocjacyjnych / czy co tam w jakim języku istnieje.
Ale jak na wejściu od razu mapujemy do encji Osoba?
java
@patch
@path("/{id}")
public Osoba update(@pathParam Long id, Osoba patch) {
serwis.zaktualizuj(id, patch);
}
Problem w tym, że:
- pozostałe pola klasy Osoba zostaną zainicjowane jako null
- jeśli przy update zignorujemy pola null, to nie wyzeruje się drugie imię
- jeśli przy update nie zignorujemy pól null, to błędnie wyzeruje się płeć i data chrztu
To może inaczej?
java
@patch
@path("/{id}")
public Osoba update(@pathParam Long id, Map<String,Object> patch) {
serwis.zaktualizuj(id, patch);
}
Ok, teraz w mapie mamy tylko te pola, co chcemy zaktualizować i to powinno zadziałać.
https://stackoverflow.com/questions/10290621/how-do-i-partially-update-an-object-in-mongodb-so-the-new-object-will-overlay
Czyli robimy $set
Używam Panache w Quarkusie i tam jest PanacheMongoRepositoryBase::update() który to robi.
Ale jest jeszcze jeden problem, bo trzeba zrobić walidację, czy takie pola w encji faktycznie istnieją i czy typ się zgadza, bo nie chcemy, aby ktoś wrzucił śmieci i potem aplikacja się wysypie. Jeśli pól w encji jest 100, to pisanie takich walidacji ręcznie jest czasochłonne. Jest kilka opcji, aby taką walidację przeprowadzić automatycznie:
- dla każdego klucza w mapie - sprawdzić, czy w klasie Osoba istnieje pole o takiej nazwie, a jeśli tak, to czy typy się zgadzają - no i z typami może być problem, bo o ile porównanie typów liczbowych i ciągów znaków spoko, o tyle daty (jest wiele klas i wiele formatów dat), enumy i nie wiadomo co jeszcze - brzmi jak wynajdowanie koła na nowo
- spróbować utworzyć instancję klasy i wrzucić wartości - co przy m.in. datach też może być czasochłonne
- ObjectMapper z biblioteki Jackson - jeśli skonwertuje mapę do klasy Osoba, to uznajemy, że jest ok - przy czym trzeba go skonfigurować tak, by rzucał wyjątkami, gdy pola nie ma w klasie lub gdy się typy nie zgadzają
A może w ogóle źle podchodzę do tematu? Może coś takiego już istnieje w Panache lub frameworku Quarkus?
#quarkus #java #mongodb #programowanie #panache
Komentarz usunięty przez autora