Techniki Zaawansowane
8 godz. 35 min · Java · Full-stack i Programowanie
Rafał SolarskiW poczatkowych lekcjach przyjrzymy sie pokladowi, na jakim bedziemy uruchamiali nasze programy. Wykorzystamy VisualVM do podgladania parametrów JVM. Zobaczymy równiez jakie zasoby sa tam dostepne oraz dowiesz sie jak monitorowac to, czy dobrze z nich korzystamy. Opowiemy Ci tez miedzy innymi o tym, jak zrobic heap i thread dump, oraz jak wlaczyc logi GC.
Kolejne lekcje kursu zostaly poswiecone wyrazeniom regularnym. Wyrazenia regularne mozemy wykorzystac nie tylko do walidacji danych wprowadzania przez uzytkownika, ale równiez do dzielenia tekstu oraz wyluskiwania wystapien wzorców w duzym tekscie. W tym rozdziale dowiemy sie miedzy innymi tego, jak mozemy wykorzystac ten potencjal z poziomu Javy.
Dzieki typom generycznym jestesmy w stanie osiagnac bezpieczenstwo typów w trakcie kompilacji przy zachowaniu elastycznosci pisanego kodu. W nastepnym rozdziale kursu przyjrzymy sie temu, jak mozemy je wykorzystac, oraz w jaki sposób czasami nalezy z tego bezpieczenstwa zrezygnowac.
Interfejsy funkcyjne to sposób na przeniesienie odrobiny swiata programowania funkcyjnego do Javy. Gdy polaczymy je z wyrazeniami lambda oraz API strumieni pozwola nam pisac te sama logike w duzo bardziej przejrzysty sposób.
Kolekcje, czyli listy, mapy, zbiory i kolejki to jedne z najczesciej wykorzystywanych klas w codziennej pracy. To jak dobrze poznamy ich mozliwosci ma ogromny wplyw na to, w jaki sposób bedziemy podchodzili do rozwiazywania wyzwan na naszej drodze.
System plików to zasób bez którego ciezko sobie poradzic. Pozwalaja nam na dostarczanie konfiguracji, danych wejsciowych i wyjsciowych, a przez to równiez integrowanie ze soba calych systemów.W tym rozdziale nauczymy sie korzystac z tych dobrodziejstw w bezpieczny sposób wykorzystujac m.in. IO Streams.
Trzymanie daty w String to niekoniecznie najwygodniejszy sposób. Juz od pewnego czasu Java dysponuje bardzo wygodnym Date&Time API - zobaczymy, co mozemy w nim znalezc.
Wielowatkowosc nie jest prosta... i dlugo tak jeszcze pozostanie. Nawet jesli korzystamy z frameworków, które próbuja ja przed nami ukryc, to ciagle musimy byc swiadomi problemów jakie sie z nia wiaza. W tym rozdziale poznamy glówne problemy na jakie mozna natrafic programujac wielowatkowo w Javie. Poznamy równiez klasy, które zdecydowanie pomoga nam zapanowac nad ta zlozonoscia.
JDBC to najbardziej podstawowy sposób laczenia sie z baza SQL z poziomu Javy. W wielu systemach/aplikacjach stosuje sie rozwiazania ORM takie jak JPA/Hibernate. Mimo wszystko warto wiedziec jak to pod spodem dziala oraz umiec poradzic sobie w aplikacjach, gdzie wybrano bardziej "lekkie" podejscie niz Hibernate.
Na koniec kursu wykorzystamy zdobyta wiedze, aby stworzyc prosta aplikacje pozwalajaca na przechowywanie danych o wydatkach. Po stworzeniu coreu aplikacji, mozesz spróbowac uzupelnic go za pomoca GUI.
Ten kurs stworzony zostal przede wszystkim z mysla o osobach, które juz poznaly podstawy jezyka, takie jak zmienne, mechanizmy kontroli wykonania, klasy, typy generyczne.Jezeli chcesz poczuc sie swobodnie nie tylko jesli chodzi o mechanizmy jezyka, ale równiez pod wzgledem znajomosci standardowej biblioteki Javy - to kurs w sam raz dla Ciebie. Materialy beda przydatne dla studentów, którzy znaja juz podstawowa skladnie Javy; programistów Javy chcacych poszerzyc lub uporzadkowac swoja wiedze; programistów innych jezyków, którzy chca poznac inny stack technologiczny.
Cześć w tej lekcji pokażę ci jak zadbać
o spójność operacji które muszą być atomowe na przykład jak przy przelewaniu
pieniędzy tak jeżeli mamy powiedzmy jakąś osobę która wysyła
jakieś pieniądze do drugiej tak najpierw w pierwszej osobie w
banku jest robiony tak zwany debit czyli powiedzmy są pobierane te pieniądze
z konta a następnie jest zrobiony credit w drugim koncie te operacje
są w pewien sposób nierozłączne tak bo gdybyśmy na przykład mieli
jakiś błąd pomiędzy tymi operacjami to jedna osoba powiedzmy
będzie miała mniej pieniędzy a druga osoba w ogóle nie dostaje tych pieniędzy więc będzie taki
niespójny stan tak takie operacje powinny być atomowe
transakcyjne tak dzięki transakcjom na bazie danych jesteśmy
w stanie to łatwo osiągnąć tutaj mamy przykład taki klasyczny właśnie
operacji debit credit mamy poza tym że ładujemy trochę
danych do bazy między innymi dwa konta tak do tabeli
accounts w której jest przechowywany id oraz balance to
mamy właśnie też operację make transfer i tutaj mówimy że zrób trasfer od
do na taką sumę ta suma jest przechowywana w groszach żeby
w bazie przechowywać integera z tego względu że jest to trochę bezpieczniejsze
niż na przykład wykorzystywanie double które ze względu na swoją reprezentację
niedokładnie przedstawiają jaki to jest powiedzmy jaka jest wartość pod
spodem więc dlatego używam tutaj powiedzmy integera tak ale to jest taka dygresja
taki szczegół okej mamy ten make transfer i tutaj mamy
debit tak i credit kredyt zabieramy pieniądze później je
przekazujemy do jakiegoś innego konta okej no i tutaj wykorzystujemy
prepared statement oczywiście okej sprawdźmy czy ta operacja się tutaj
powiedzie powiodła się tak dane się zmieniły tak
tutaj teraz zostało przelane 100 zł tak na to drugie konto okej
i teraz zobaczmy co się wydarzy jeżeli tutaj na
przykład dodamy właśnie jakiś wyjątek
po drodze jak widzimy 100 zł zostało zabrane z pierwszego
konta ale nie pojawiło się na drugim koncie tak te pieniądze trochę zniknęły
z tego względu że mieliśmy tutaj błąd techniczny po drodze w sytuacji
kiedy tutaj złapaliśmy wyjątek i nie jesteśmy pewni co się tutaj
wykonało czy debit się wykonał a jeżeli się wykonał to czy credit
też w takiej sytuacji powinniśmy zrollbackować transakcje czyli
powiedzmy wykorzystać mechanizm transakcji który sprawia że pewne operacje są
zbierane w takie powiedzmy czanki jakiś taki większą
całość są wrzucane do bazy i w bazie się mówi w ten
sposób jeżeli one wszystkie przeszły to okej to zatrzymaj
ten stan które one powiedzmy tam zmieniły a jeżeli któraś był jakikolwiek
błąd wśród tych operacji to otwórz wszystko tak czyli przywróć
ten stan który był w ogóle przed uruchomieniem całej tej operacji całego tego powiedzmy
batcha czy powiedzmy właśnie czanka okej
i do tego właśnie ze względu że transakcje to jest taki byt
powiedzmy bazodanowy to też w jdbc jest wsparcie dla tego
typu właśnie operacji które mają być transakcyjne w pierwszej
kolejności jeżeli chcemy skorzystać z transakcji to na
connections ustawia się flagę autocommit
tutaj możemy właśnie zrobić connection set autocommit i tę
flagę musimy ustawić na false tak dzięki temu możemy manualnie
commitować bądź rollbackować transakcje domyślnie jest na true
i teraz to auto commit jeżeli jest włączone tak czyli
powiedzmy jakbyśmy to sobie albo tutaj usunęli albo byśmy spojrzeli
jak jak to powiedzmy działo się tutaj wcześniej tak
bo dopiero od tego momentu obowiązuje autocommit to
tutaj wcześniej każda operacja która była wykonywana tak
każdy z tych insertów czy ddl tworzy sobie taką powiedzmy transakcje
taką mini transakcje tak i ona powiedzmy jeżeli przeszła ta operacja
to była automatycznie commitowana było powiedziane okej wszystko przeszło idziemy
dalej tak od tego momentu jeżeli sobie ustawimy to false to właśnie
każdą tutaj operację będziemy musieli samodzielnie manualnie commitować
ale dzięki temu też możemy je commitować na przykład po kilka tak czyli powiedzmy zrobiliśmy
dwie operacje jakieś tak pierwsze nie commitujemy
commitujemy dopiero wtedy kiedy mamy pewność że druga też przeszła taka sytuacja jak tutaj
mamy właśnie okej tutaj na początek tak jeżeli
zdobędziemy z powiedzmy dostaniemy jakiś wyjątek tak to robimy connection
rollback tak tutaj i wtedy to nas cofnie do poprzedniego
commita czyli w momencie kiedy tu wcześniej było ustawione autocommit tak
to ostatni commit gdzieś tutaj przy tym insercie się zadział
tutaj też trzeba być bardzo czujny czy wcześniej
był commit czy nie bo możliwe że będziemy musieli tutaj zrobić sobie commita
na przykład tak na nasze potrzeby tutaj akurat nie okej
dobra czyli ten rollback jeżeli pojawił się jakiś exeption to nas cofnie do
ostatniego commita ale też musimy powiedzmy te dane z tego względu że automatycznie
nam się nie scommitują to na koniec tutaj też musimy zrobić connection commit
tak dobrze i teraz zobaczmy jak to zadziała w naszym
przypadku okej widzimy że dane są identyczne
jak na początku tak w drugiej klatce okej teraz sobie zakomentujmy
może to throw critical który rzuca ten wyjątek okej
i widzimy że ten happy path też prawidłowo zmienia powiedzmy
te dane nie poza tym że możemy wykorzystać commit
i rollback jeszcze jest coś takiego jak save point i save point to
jest powiedzmy mechanizm który pozwala nam się zrollbackować do jakiegoś konkretnego miejsca
na przykład tak jak tutaj mamy w transferze możemy
się cofnąć do stanu który był tutaj
na początku save pointowany tak tutaj jest zrobiony save point
na connection i musimy sobie zapisać ten save point i później po prostu
przy rollbacku podajemy do którego save pointa tak ich może
być kilka a i to nie jest na początek to
może być wydawać się takie tożsame z tym żeby zrobić tu commit
po prostu nie tak tylko no właśnie to
zależy od kontekstu teraz czas na kontekst powiedzmy ten
rollback z save point'em przyda nam się w momencie kiedy mamy
na przykład takie dwa poziomy tego że coś się udało albo nie powiedzmy
że mamy jedną transakcję taką dużą major transaction i pod
spodem mamy kilka transakcji mniejszych tak na przykład jak tutaj wysyłam
pieniądze od jednego gościa na przykład do innych tak
do trzech tutaj podaje listę id po 100 zł i
teraz jest taki powiedzmy założenie biznesowe
że jeżeli połowa z tych transakcji to
będą faile ponad połowa tak to wtedy cała
transakcja nie wychodzi tak jest robiony rollback wszystkiego
ale jeżeli na przykład ponad połowa jest prawidłowa
tak powiedzmy mamy ponad połowę sukcesów czyli tutaj byśmy
mieli coś takiego w przypadku transakcji byśmy mieli że dwa były success'y
jeden fail no to wtedy jest
success tej większej major transaction tak no
ale poza tym że zrobimy powiedzmy commit na właśnie
na tej większej transakcji to nie możemy zrobić commita na tej
jednej transakcji która nie wyszła tak bo tam powiedzmy pobrano pieniądze
ale ich nie przelano tak byśmy mieli niespójny
stan wtedy tak więc wcześniej zanim powiedzmy jest
zrobiona jest jest robiona każda z tych tranzakcji i ona każda z nich
jeżeli nie wyszła to ona się rollbackuje sama albo commituje
się sama ale o taki mały fragment tak commitować się akurat nie
musimy je scommitujemyna koniec wszystkie naraz jeżeli powiedzmy mamy
pewność że jeżeli któraś z nich nie wyszła to ona sama się z rollbackowała
o mały state tak o mały kawałek nie może być tak że na przykład trzecia
się udała druga się udała i trójka zrobiła rollback do ostatniego
commita tak bo ona by się teraz cofnęła gdzieś dotąd tak skasowała by
wtedy to co zostało wyprodukowane w bazie w trakcie tej
pierwszej transakcji tak okej tu ja mam to zaimplementowane mniej
więcej to wygląda trochę strasznie z tego względu że obsługa tego
powiedzmy tych rollbacków też w try finally jest taka trochę uciążliwa okej
mamy w każdym razie jakiś counter na początek tak który równy jest 0
i on liczy powiedzmy dla każdej transakcji tutaj w pętli odpalonej zlicza
ile się udało a ile się nie udało tak tutaj na podstawie tej flagi success no
i na koniec patrzy to jest wyliczany threshold że
jeżeli ponad połowa była nieprawidłowa no
to wtedy robimy fail całości i robimy rollback i teraz
ten rollback on nie cofnie się do ostatniego save pointu tylko on się cofnie do ostatniego
commita czyli do tej takiego grubego commita tak a okej
i jest robiony rollback całości niezależnie czy pomniejsze transakcje
się udały czy nie okej ale jeżeli powiedzmy jest inaczej jeżeli ten threshold
nie jest przebity no to wtedy robimy
commit na wszystkim tak nawet jeżeli któreś
mniejsze transakcji się powiedzmy nie udały ale one nie przebiły tego
thresholdu na którym nam zależy i teraz to żeby tutaj zrobić commit
bezpiecznie tak z czystym sumieniem w tym momencie to
tutaj musimy jeszcze przerobić w tym make single transfer
on ta operacja musi dbać o to że jeżeli ona się nie
powiedzie tak mam to jakiś exeption pomiędzy to
ona sama się zrobi brakuje do swojego stanu na początku tak tutaj
tworzymy save point on musi być spoza powiedzmy
przed try utworzony ponieważ tutaj w catchu będziemy go obsługiwali
tak no i jeżeli on nie jest nullem czyli powiedzmy
to się udało tak ta pierwsza linia no to wtedy
rollbackujemy do niej a jeżeli ta pierwsza linia nawet się nie udała to nie ma
do czego rollbackować właśnie nie trzeba się przejmować tak okej a jeżeli powiedzmy całość
przeszła tutaj nie robimy commita bo w tym momencie byśmy powiedzieli że
poprzednie transakcje się udały i ich nie trzeba rollbackować no
a tego nie jesteśmy pewni prawda więc powiedzmy odpowiadamy tylko za
siebie w tym momencie tak no okej i zwracamy true bądź false w zależności
od tego czy się udało czy nie tak okej tutaj ta
operacja pośrodku aby to jakoś powiedzmy majstrować
przy tym czy one powiedzmy większość była failów czy sukcesów to po prostu jest
rzucany wyjątek jeżeli id jest podzielny przez dwa tak
okej no i teraz sobie sprawdźmy tutaj mamy dwa trzy cztery więc większość
z tych id jest podzielna przez dwa więc powinniśmy mieć dwa
faile pomniejsze i fail całości więc rollback wszystko czyli
żadne dane nie powinny powinny się zmienić w tym momencie sprzed całej
transakcji i po całej transakcji okej
tutaj mamy migawkę po transakcji i tu mamy wcześniej widzimy
jest fail jednej mniejszej ona jest rollbackowana i mamy fail
drugiej mniejszej jest też rollbackowana i później threshold nam tutaj wpadł tak
i rollbackujemy wszystko no i nie ma zmian tak i teraz jeżeli zmienimy
sobie tę czwórkę na piątkę to zobaczymy tutaj już teraz ten threshold
nie powinien być przebity widzimy że mamy powiadomienie że jedna z
nich się nie udała jest rollbackowana to jest od jedynki do dwójki tak i
tutaj widzimy że w dwójce się nie zmieniło ale widzimy że pozostałe dwie
tutaj się zmieniły zostały przelane pieniądze i zostało tutaj
po 100 zł zabrane od pierwszego konta prawda ale
po 100 zł i tyle nie zostało odebrane 300 tak czyli powiedzmy mimo że ta
jedna z tych transakcji do dwójki się
nie udała to ona została całkowicie zrollbackowana
tak czyli mamy spójny stan okej raczej
z tych save pointów nie będziesz zbyt często korzystał jest to taki powiedzmy trzeba mieć
bardzo taki specyficzny przypadek żeby z tego skorzystać lub po prostu bardziej
robić rzeczy tak w bazie tak tam powiedzmy nie przez jdbc tylko
tam pisząc jakiś procesy procedury storage'owane powiedzmy w bazie
to czasami się tego używa okej tutaj zauważ też że
obsługa tych rollbacków i commitów jest trochę
taka no nie jest zbyt wygodna tak trzeba dużo tych try finally
robić jeżeli chcesz mieć faktycznie na przykład ja miałem takie
założenie chcę ustawić stan autocommit
który był przed na końcu tak no i wtedy muszę obsłużyć
to że też commit i rollback może się nie może się nie udać tak więc tutaj
no jest trochę takiego zamieszania ale jeżeli będziesz
używał na przykład właśnie hibernate albo jpa to tam
takie właśnie rollbacki zapewnienie tranzakcyjności
możesz zapewnić używając po prostu odpowiedniej adnotacji wtedy
mówisz że na przykład metoda make transfer tu ją adnotujesz jakieś
powiedzmy transaction i
ona powiedzmy spring z hibernate zapewnią na przykład że ta metoda jeżeli
coś wrzuci no to ona powiedzmy cofnie się do tego co
było zrobione przed tą metodą tak czyli na początku robi save bądź
go nie robi na koniec robi po prostu rollback tak więc jest to trochę wygodniejsze
okej to wszystko co chciałem ci pokazać w kontekście transakcji dzięki
wielkie i do zobaczenia