Aktywne Wpisy
TrudnyMinus +45
kingszajs +3
Polecacie jakąś grę na majówkę? Szukam czegoś dobrego na PC lub PS5. Ogólnie mam za sobą wszystkie znane topowe gięty, RDRy, TLOU, GODy, Horizony, Ghost of Tsushima, Days Gone, etc. Chyba maksymalnie wykorzystałem potencjał rynku gier...
Gry multiplayer odpadają, nie kręcą mnie. Szukam czegoś co naprawdę wciągnie pod kątem fabuły i też żeby reszta aspektów trzymała sensowny poziom.
Rynek gier strasznie się skiepscil albo już ewidentnie jestem stary ( ͡° ʖ
Gry multiplayer odpadają, nie kręcą mnie. Szukam czegoś co naprawdę wciągnie pod kątem fabuły i też żeby reszta aspektów trzymała sensowny poziom.
Rynek gier strasznie się skiepscil albo już ewidentnie jestem stary ( ͡° ʖ
- 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