Mam takie zagadnienie:
- 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
@Dataclass 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-overlayCzyli 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
Już nie wspomnę o tym, że branża "auth" to naciągacze, którzy wmówili ludziom, że autentykacja i autoryzacja to coś niemożliwe skomplikowanego. Z "never roll your own cryptography" zrobili "never roll your own auth" z tym skróconym "auth" jako dodatkową manipulacją.