Przemyślenia architekta IT

Menu
  • Strona główna
  • O mnie
  • Co czytam
  • Czego się uczę
Menu

Jak dorosłem do tego, żeby nie używać ORM’a

Posted on 3 lutego 202030 września 2020 by Tomasz Sokół

Kiedy jako młody programista poznałem Hibernate byłem oczarowany. Idea przykrycia relacyjnej bazy danych zestawem obiektów wydawało mi się czymś mega innowacyjnym. W końcu programowaliśmy obiektowo nie? Były to czasy Spring’a 2.0, a ja zaczynałem jako młodszy programista pracę nad projektem dla jednej z firm udzielających pożyczek na niewielkie kwoty.

Architektura trójwarstwowa, SimpleFormController + Velocity na froncie oraz oczywiście obiekty DAO z zaprzęgniętym Hibernate. Masa obiektów encji z naćkanymi kolekcjami zagnieżdżonymi. Pamiętam słowa naszego ówczesnego architekta. „Tylko pamiętaj, fetchyType=Lazy, nie chcemy przecież zaciągać obiektów z bazy niepotrzebnie. Zostaną dociągnięte, gdy się do nich odwołasz”. Encje nierzadko leciały aż na widoki.

To Lazy nie jest jednak takie zarąbiste

Szybko okazało się, że świat nie jest taki kolorowy. Stało się to oczywiście za sprawą LazyInitializationException. Ale o co chodzi? – pomyślałem. A no o to, że te zagnieżdżone kolekcje, co to miały się magicznie zainicjować dopiero wtedy, gdy ich potrzebujemy, to jednak nie jest zawsze taki wspaniały pomysł. Istnieje coś takiego jak sesja Hibernate.

Niech pierwszy rzuci kamieniem ten, kto nie wpadł na pomysł aby pozbyć się tego problemu wykonując metodę size() na problematycznej kolekcji ;). Jednak surowy wzrok architekta i krótki wykład o problemie n+1, nie pozostawiły złudzeń. To był kiepski pomysł.

Na pewien czas świat stał się znowu piękny, gdy któryś ze starszych kolegów wspomniał o istnieniu OpenSessionInViewFilter :D.

Te zapytania pod spodem są jakieś pokraczne i jakoś ich dużo

Sielanka trwała do czasu, kiedy rozpoczęły się testy UAT. Aplikacja w wielu miejscach działała jakoś tak wolno. Okazało się, że Hibernate potrafi generować nie zawsze optymalne zapytania, a do tego potrafi generować je w ilości większej niż się zakładało. Wydajność aplikacji pozostawiała wiele do życzenia.

ORM jest super ale tylko jeśli wiesz jak on działa

Każda abstrakcja cieknie. A jeśli się nie wie co siedzi pod spodem, to cieknie jeszcze szybciej. To szczególnie dotyczy ORM’ów. Musisz dokładnie wiedzieć jak one działają, jeśli chcesz ich używać. Od samego początku musisz zwracać uwagę jakie zapytania zostaną finalnie wysłane do bazy danych. Jeśli myślisz, że stosując ORM’a zrzucasz z siebie ciężar projektowania optymalnych kwerend SQL, to muszę Cię rozczarować. Prędzej czy później takie podejście odbija się czkawką. Wydaje mi się, że najrozsądniej jest najpierw zaprojektować kwerendę SQL, a potem próbować zamodelować ją z użyciem klas ORMa. No chyba, że implementujemy prostego CRUDa.

Przy przetwarzaniu dużej ilości danych ORM się nie sprawdzi

Po raz pierwszy przekonałem się o tym, że ORM nie jest do wszystkiego, gdy musiałem zaimplementować import dużej ilości danych. Moja pierwsza implementacja oczywiście używała ORM’a. Dane ładowane były do jednej tabeli, żadnych relacji, struktura płaska. Co mogło pójść nie tak? Prawo Murphy’ego mówi „Jeśli coś może pójść nie tak, to na pewno tak się stanie”. Co więc okazało się problemem? Czas. Problemem był czas wykonania całej operacji. ORM generował za duży nakład czasowy. Nauczyłem się jednego. Operacje na dużych zbiorach danych trzeba implementować z użyciem native query. W Springu idealnie nadaje się do tego JdbcTemplate.

Istnieją alternatywy do ORM’a

Po raz pierwszy decyzję o nie używaniu ORM’a podjąłem, gdy zostałem zaangażowany w przepisanie systemu legacy. Był to system backend’owy, w którym znaczna część logiki biznesowej była zaszyta bardzo blisko, lub w samych kwerendach SQL. Zapytanie były sklejane ze String’ów i były tak złożone, że bardzo często nie mieściły się na ekranie monitora. Wiedzieliśmy już, że ORM się nie nada. Zaczęliśmy zatem rozglądać się za alternatywami. Wybór padł na QueryDLS. Framework sprawdził się w dużej części przypadków. Jednak złożoność zapytań okazała się w wielu przypadkach granicą nie do pokonania. Pojawianie się unii lub konieczność używania wewnątrz zapytań hint’ów specyficznych dla bazy Oracle spowodowały, że musieliśmy przygotowywać zapytania w czystym SQL’u. Postanowiliśmy używać JdbcTemplate i PreparedStatement. Po raz kolejny również wydajność okazała się znacznym problemem. QueryDSL był w wielu przypadkach zbyt wolny.

Konkluzja

W naszej branży mamy tendencję do podążania za modą. Próbujemy znajdować złote środki na rozwiązywanie wszystkich problemów. Lepiej jednak jest dobierać właściwe narzędzia do właściwych problemów. Jeśli uznasz, że nie potrzebujesz ORM’a i masz ku temu przesłanki, nie używaj go.

Jeśli podobają Ci się treści na moim blogu zostaw swój email. Będę Cię informował o nowych artykułach. Zero spamu same konkrety.

* pola wymagane

Chcesz dostawać powiadomienia o nowych artykułach? Zostaw swój email.

Najnowsze wpisy

  • 7 kroków do przejęcia systemu od innego dostawcy
  • Młody programisto! 7 porad od starszego kolegi
  • Jak dorosłem do tego, żeby nie używać ORM’a
  • Drivery architektoniczne. Czym są i co może się wydarzyć, gdy odkryjemy je zbyt późno. Historia prawdziwa.
  • Wizualizacja architektury zgodnie z modelem C4. Podejście praktyczne

Kategorie

  • Architektura
  • Procesy
  • Zespół
Polityka prywatności
©2021 Przemyślenia architekta IT | WordPress Theme by SuperbThemes
Serwis wykorzystuje pliki cookies. Korzystając ze strony wyrażasz zgodę na wykorzystywanie plików cookies.Tak. Zgadzam się Reject Dowiedz się
Privacy & Cookies Policy

Privacy Overview

This website uses cookies to improve your experience while you navigate through the website. Out of these cookies, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may have an effect on your browsing experience.
Privacy Overview

This website uses cookies to improve your experience while you navigate through the website. Out of these cookies, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may have an effect on your browsing experience.

Necessary Always Enabled

Necessary cookies are absolutely essential for the website to function properly. This category only includes cookies that ensures basic functionalities and security features of the website. These cookies do not store any personal information.

Non-necessary

Any cookies that may not be particularly necessary for the website to function and is used specifically to collect user personal data via analytics, ads, other embedded contents are termed as non-necessary cookies. It is mandatory to procure user consent prior to running these cookies on your website.