Analiza porównawcza technologii implementacji warstwy
Transkrypt
Analiza porównawcza technologii implementacji warstwy
XVI Konferencja PLOUG Kościelisko Październik 2010 Analiza porównawcza technologii implementacji warstwy dostępu do danych w aplikacjach ADF Paweł Boiński Politechnika Poznańska [email protected] Abstrakt. Twórcy wielowarstwowych aplikacji ADF najczęściej implementują warstwy dostępu do bazy danych korzystając z jednej z dwóch kluczowych technologii: ADF Business Components lub Enterprise Java Beans. Celem tego referatu jest porównawcza analiza obu rozwiązań, uwzględniająca aspekty funkcjonalne, narzędziowe i efektywnościowe. Autor przedstawi m.in. wyniki złożonego eksperymentu wydajnościowego, w ramach którego badano efektywność realizacji operacji dostępu do danych. Informacja o autorze. Paweł Boiński pracuje w Instytucie Informatyki Politechniki Poznańskiej. Specjalizuje się w systemach baz danych, przestrzennych bazach danych i eksploracji danych. Analiza porównawcza technologii implementacji warstwy dostępu do danych... 295 1. Wprowadzenie Java EE [JEE] jest platformą, która bardzo często stanowi podstawę oprogramowania korporacyjnego. W praktyce, Java EE, stanowi zaledwie zbiór zasad i specyfikacji określających strukturę oprogramowania budowanego w oparciu o architekturę wielowarstwową. Ze względu na bardzo rozbudowany zakres opisywanych zagadnień, platforma Java EE może stanowić dla wielu programistów i projektantów zbyt skomplikowane środowisko. Przez wiele lat opracowywano wzorce projektowe oraz tzw. najlepsze praktyki w pracy z Java EE. Ich wykorzystanie wiąże się jednak często z koniecznością pisania dużej ilości kodu, który nie jest przeznaczony do wykonywania konkretnych funkcji biznesowych, lecz służy do implementacji struktury aplikacji. Wymusiło to na deweloperach poszukiwanie nowych rozwiązań. Wraz z debiutem środowiska Oracle JDeveloper 10g Release 2 wprowadzona została koncepcja Oracle Application Development Framework (w skrócie: Oracle ADF) [ADF]. Oracle ADF jest frameworkiem wykorzystującym platformę Java EE i zawiera implementację najbardziej popularnych wzorców projektowych. Dodatkowo wprowadzone zostały edytory wizualne, dzięki którym możliwe jest szybkie tworzenie najczęściej spotykanych elementów aplikacji. Zgodnie ze schematem wyznaczonym przez Java EE, Framework Oracle ADF definiuje wielowarstwową architekturę aplikacji. Jedną z kluczowych cech Oracle ADF jest pozostawienie programiście dużej swobody wyboru konkretnych technologii implementacji każdej z warstw aplikacji. Wybór technologii, choć uelastycznia pracę projektanta aplikacji, wymaga od takiej osoby znacznie większego zakresu wiedzy na temat dostępnych rozwiązań. Zły wybór na etapie projektowania aplikacji może mieć poważne konsekwencje w dalszych krokach procesu wytwarzania oprogramowania. O ile na etapie implementacji zmiana technologii może być stosunkowo prosta, o tyle zdiagnozowanie złego wyboru na etapie testowania lub (co gorsza) na etapie użytkowania, może skutkować bardzo wysokimi kosztami naprawy tej sytuacji. Jeden z czarnych scenariuszy polegać może na złej ocenie wydajności konkretnej technologii w odniesieniu do skalowalności. Problem ten często pojawia się zwłaszcza w aplikacjach internetowych, gdzie ilość danych i użytkowników może wzrosnąć w stopniu dramatycznym w bardzo krótkim czasie. W ramach niniejszego tekstu podjęta została próba odpowiedzi na pytanie, jaką strategię wybrać w implementacji warstwy dostępu do danych w aplikacjach ADF w sytuacji, gdy spodziewana jest znacząca ilość danych przetwarzanych przez aplikację. Rozważania dotyczą przede wszystkim aspektu wydajnościowego przyjętego rozwiązania, ale poruszone zostały także kwestie funkcjonalności i dostępności specjalizowanych narzędzi. Analizie poddano dwie popularne technologie dostępu do danych: Enterprise Java Beans 3.0 (w skrócie: EJB 3.0) [EJB30] oraz ADF Business Components. Struktura tekstu jest następująca. W rozdziale drugim przedstawiona została architektura typowej aplikacji ADF wraz z umiejscowieniem w niej warstwy dostępu do danych. Opisano również, w zwięzłej formie, technologie implementacji, które zostały poddane analizie: ADF Business Components oraz Hibernate i EclipseLink. W rozdziale trzecim zostało opisane środowisko testowe oraz rodzaje przeprowadzonych testów wraz z ich wynikami i interpretacją. 2. Warstwa dostępu do danych w architekturze Oracle ADF Architektura Oracle ADF oparta jest o popularny wzorzec Model-View-Controller (w skrócie: MVC), który ułatwia utrzymywanie i ponowne wykorzystywanie implementowanych komponentów aplikacji. Oracle ADF rozszerza trzy warstwy MVC i składa się z następujących warstw podstawowych: • widok – zawiera implementację interfejsu użytkownika, 296 Paweł Boiński • kontroler – kieruje przepływem sterowania aplikacji (np. pomiędzy stronami aplikacji inter- netowej), • usługi biznesowe – udostępnia dane z różnych źródeł, • model – pośredniczy między warstwą usług biznesowych a kontrolerem i widokiem. Wymienione warstwy są ze sobą luźno powiązane, co skutkuje dużą elastycznością w doborze konkretnej techniki implementacji każdej z nich. Na przykład, warstwa widoku może wykorzystywać interfejs WWW lub opierać się na aplikacji desktopowej korzystającej z komponentów ADF Swing do prezentacji danych pochodzących z różnych źródeł danych. Na szczególną uwagę zasługuje warstwa modelu, która stanowi element pośredniczący w komunikacji kontrolera i komponentów z warstwy widoku z obiektami odpowiedzialnymi za interakcję z bazą danych (lub innym źródłem danych). Warstwa modelu zaproponowana przez firmę Oracle, stała się podstawą dla specyfikacji JSR-227 „A Standard Data Binding & Data Access Facility for J2EE” [JSR227]. W dużym uproszczeniu można powiedzieć, że warstwa modelu w Oracle ADF, udostępnia pojedynczy interfejs dla komunikacji z dowolną implementacją usług biznesowych. Warstwa usług biznesowych dostarcza funkcjonalności w zakresie operacji takich jak utrwalanie danych, zarządzanie transakcjami, mapowanie obiektowo-relacyjne oraz wykonywanie przetwarzania logiki biznesowej. Wśród technologii implementacji tej warstwy można wyróżnić m.in.: • proste klasy Java, • usługi typu web services, • EJB, • Oracle ADF Business Components. W przypadku EJB, w 2006 roku, została sformułowana specyfikacja definiująca wersję oznaczoną numerem 3.0 tej technologii. W skład specyfikacji wszedł również dokument [JSR220] opisujący zarządzanie trwałością danych oraz odwzorowanie obiektowo-relacyjne w aplikacjach Java EE (a także Java SE w wersji 5 i 6). Technologia ta znana jest pod nazwą Java Persistence API (w skrócie: JPA) i w znaczący sposób upraszcza model przetwarzania, znany z poprzedniej wersji EJB. Przedstawiona różnorodność metod dostępu do danych sprawia, że na etapie projektowania aplikacji konieczne staje się rozważenie wielu czynników wpływających na wybór konkretnej technologii. Wśród najważniejszych aspektów można wyróżnić następujące elementy: • znajomość technologii przez zespół programistów, • dostępność dokumentacji, • dojrzałość, • wsparcie producenta, • zakres oferowanych mechanizmów, • wydajność, • skalowalność, • cenę. W dalszej części artykułu zostanie omówiony problem wyboru technologii implementacji warstwy usług biznesowych, a konkretnie metod dostępu do danych znajdujących się w bazie danych. Jako nadrzędne kryterium decydujące o wyborze przyjęto wydajność operacji odczytu, zapisu i modyfikacji danych. Analiza porównawcza technologii implementacji warstwy dostępu do danych... 297 2.1. Technologie implementacji warstwy dostępu do danych Twórcy architektury Oracle ADF, dając do wyboru projektantowi sposób dostępu do trwałych danych, nie wskazali „jedynego słusznego” rozwiązania, chociaż podano tzw. zalecane zestawy technologii w zależności od umiejętności programistów: • ADF Business Components, JSF, JSF Faces – dla osób migrujących z technologii Oracle Forms [Ora06][Ora10a] • EJB 3.0/JPA, JSF, JSF Faces – dla osób, które mają doświadczenie z programowaniem Java EE oraz dla wszystkich nowych aplikacji [Ora10b]. Firma Oracle udostępnia dla programistów szereg książek dokumentujących zarówno wykorzystanie ADF Business Components, jak również EJB 3.0/JPA. Należy zwrócić jednak uwagę, że zdecydowana większość publikowanych materiałów o ADF opisuje aplikacje wykorzystujące ADF Business Components. Przeprowadzone badania wydajności obejmowały porównanie ADF Business Components z dwoma implementacjami EJB 3.0/JPA: Hibernate [HIB] oraz EclipseLink [EL]. W kolejnych podpunktach zostały krótko przedstawione powyższe technologie dostępu do danych. 2.1.1. ADF Business Components Komponenty biznesowe wywodzą się z technologii Business Components for Java (w skrócie: BC4J) i od wielu lat stanowią jedną z kluczowych technologii firmy Oracle. Wśród oferowanych funkcjonalności można wyróżnić m.in.: • automatyczne zarządzanie odwzorowaniem obiektowo-relacyjnym, • możliwość definiowania złożonych poleceń SQL, • możliwość implementacji złożonego przetwarzania biznesowego, • obsługę transakcji, • możliwość definiowania deklaratywnych reguł poprawności, • dostęp do procedur składowanych, • obsługę list wartości (ang. list of values). W ADF Business Components można wykorzystać także deklaratywne walidatory poprawności danych: compareValidator, listValidator, rangeValidator oraz methodValidator. Sprawdzają one, odpowiednio, czy wartość jest równa podanemu literałowi, czy należy do statycznej lub dynamicznej listy wartości, czy znajduje się w zakresie wartości. W przypadku najbardziej zaawansowanego walidatora, czyli walidatora typu methodValidator, użytkownik definiuje metodę, która zwraca wartość prawda lub fałsz określającą, czy wartość została zatwierdzona lub odrzucona. W skład ADF Business Components wchodzą następujące komponenty: • obiekty encyjne – służą do reprezentacji danych (np. wierszy z relacji) i odpowiadają za trwałość i walidację danych, • asocjacje – definiują zależności relacyjne pomiędzy obiektami, • obiekty perspektyw – organizują dane z obiektów encyjnych udostępniając je innym kom- ponentom aplikacji, posiadają również możliwość filtrowania danych oraz formatowania ich reprezentacji, • moduły aplikacji – udostępniają obiekty perspektyw dla innych elementów aplikacji i od- powiadają za zarządzanie transakcjami. 298 Paweł Boiński Typowe działanie przy tworzeniu aplikacji ADF z wykorzystaniem komponentów biznesowych polega na utworzeniu obiektów encyjnych oraz asocjacji dla tych obiektów. Następnie, tworzone są obiekty perspektyw które mogą korzystać z przygotowanych obiektów encyjnych. Całość dopełniają moduły aplikacji, które stanowią interfejs dla klientów. Automatycznie tworzone są kontrolki danych implementujące JSR-227, które zapewniają współpracę z takimi komponentami jak elementy interfejsu użytkownika. Za wadę ADF Business Components można uznać rozbudowaną strukturę opisu obiektów tworzących komponenty. Klasy takich obiektów nie są klasami POJO (skrót od Plain Old Java Object) – dziedziczą po określonych klasach dostarczonych przez framework. Wpływa to również na poziom złożoności kodu. Na przykład, obiekt encji może być opisany przez cztery pliki: • pliku XML z opisem m.in.: mapowania obiektowo-relacyjnego, walidatorów poprawności danych, • pliku z definicją klasy, na której podstawie tworzone są instancje obiektu encyjnego, • pliku z definicją obiektu encyjnego, która może być użyta do niestandardowego przetwarza- nia deskryptorów z pliku XML, • pliku z klasą opisującą kolekcję encji służącą do reprezentacji obiektów w pamięci podręcz- nej dla pojedynczego użytkownika. 2.1.2. EJB3.0/JPA Idea JPA polega na jak największym uproszczeniu kodu potrzebnego do obsługi operacji komunikacji z relacyjną bazą danych wraz z jednoczesnym zachowaniem obiektowego charakteru aplikacji. JPA jest oparte na odwzorowaniu obiektowo-relacyjnym, które zakłada, że krotki przechowywane w relacjach bazodanowych są reprezentowane w postaci obiektów środowiska Java. Takie obiekty nazywane są encjami JPA i stanowią instancje zwyczajnych klas Java typu POJO. Określanie, które obiekty mają być przechowywane w bazie danych oraz zasady obowiązujące przy ich zapisie lub odczycie, specyfikowane są za pomocą plików XML lub za pomocą tzw. adnotacji języka Java. Druga z metod jest bardziej popularna, a jej główną zaletą jest prostota i zwięzłość zapisu (w stosunku do rozbudowanych plików XML). Związki pomiędzy relacjami w bazie danych reprezentowane są także w postaci adnotacji lub opisów XML. JPA wprowadza koncepcję tzw. zarządcy encji (EntityManager) będącego obiektem odpowiedzialnym za cykl życia każdej z przetwarzanych encji. Instancje klas encji, które nie zostały utrwalone przez zarządcę encji, zachowują się jak zwyczajne obiekty języka Java. Zdefiniowane zostały również takie elementy jak API dla zatwierdzania i wycofywania transakcji, czy też zarządzanie wersjami obiektów i blokowaniem krotek. Operacje odczytu obiektów odbywać się mogą przy wykorzystaniu API dla zapytań, które obejmuje zarówno zapytania nazwane (statyczne, podane np. w postaci adnotacji), jak również zapytania dynamicznie konstruowane w czasie wykonania programu. Zdefiniowany został nowy język zapytań Java Persistence Query Language (w skrócie JPQL), który jest rozbudowaną wersją Enterprise JavaBeans Query Language [EJB30]. Istnieje również możliwość wykonania natywnego polecenia języka SQL. W typowych aplikacjach Java EE, na początku tworzone są obiekty encji reprezentujące relacje w bazie danych, a następnie fasada sesji (ang. session facade), która staje się interfejsem dla klienta. W aplikacjach ADF wykorzystujących JPA, oprócz utworzenia obiektów encyjnych oraz fasady sesji, najczęściej konstruowane są kontrolki danych, które udostępniają dane i logikę z fasady sesji. Taka kontrolka danych może być następnie efektywnie wykorzystana przez komponenty interfejsu użytkownika. Pierwsza specyfikacja JPA nie zawierała uwag dotyczących pamięci podręcznej (cache) dla obiektów. W tym przypadku na większą precyzję zdecydowano się dopiero w wersji 2.0. Pomimo braku wymagań odnośnie pamięci podręcznej, wszyscy liczący się dostawcy implementacji JPA Analiza porównawcza technologii implementacji warstwy dostępu do danych... 299 w wersji 1.0 oferują jednak taki mechanizm w swoich produktach. Niniejszy artykuł dotyczy JPA 1.0. Analizie poddane zostały dwie, prawdopodobnie najpopularniejsze, implementacje JPA: Hibernate i EclipseLink. Hibernate Projekt Hibernate został zapoczątkowany w 2001 roku. Miał stać się alternatywą dla promowanej ówcześnie platformy EJB w wersji drugiej. Celem Hibernate było uproszczenie metod dostępu do danych oferowanych przez EJB2 przy jednoczesnej rozbudowie dostarczanych funkcjonalności. Hibernate został następnie przejęty przez firmę JBoss, Inc., która od tego czasu kieruje dalszym rozwojem projektu. Sama firma JBoss, Inc. została natomiast włączona w skład grupy Red Hat w roku 2006. W obecnej chwili dostępna jest trzecia wersja biblioteki Hibernate, która jest certyfikowaną implementacją standardu JPA 1.0 oraz JPA 2.0. Hibernate udostępniany jest na licencji GNU Lesser General Public License. Oznacza to, że jest darmowy zarówno dla użytku deweloperskiego, jak również w środowiskach produkcyjnych. Wychodząc poza standardowe funkcjonalności, biblioteka Hibernate oferuje m.in. własny język zapytań HQL oraz definiowane kryteria dla zapytań (ang. criteria queries). Ciekawym aspektem jest również obecność projektu NHibernate, który jest implementacją funkcjonalności Hibernate przeniesioną na platformę Microsoft .NET. Pozwala to bardzo efektywnie wykorzystać nabytą wiedzę przy pracy z różnymi projektami. Biblioteka Hibernate jest wspierana przez wiele narzędzi, m.in. przez środowiska programistyczne Netbeans oraz Eclipse. W przypadku środowiska Eclipse, jest to zbiór wtyczek wchodzących w skład projektu HibernateTools [HT]. Oferuje on takie funkcjonalności jak edytor plików XML wraz z semantycznym autouzupełnianiem, kreatory dla tworzenia konfiguracji oraz tzw. reverse engineering używany do generowania definicji na podstawie istniejącego już schematu bazy danych. EclipseLink EclipseLink wywodzi się z projektu Oracle TopLink. Firma Oracle w 2008 roku powierzyła fundacji Eclipse zarządzanie otwartym projektem opracowanym na podstawie własnego produktu. W EclipseLink znalazła się pełna funkcjonalność znana z Oracle Toplink. Szczególną uwagę powierzono zgodności ze standardami, w tym zgodności ze standardem JPA. Podobnie jak w przypadku biblioteki Hibernate, obecna implementacja EclipseLink jest zgodna zarówno ze specyfikacjami JPA 1.0 oraz JPA 2.0. W stosunku do biblioteki Hibernate, implementacja EclipseLink oferuje lepsze wsparcie dla mechanizmów bazy danych Oracle. Obejmuje to takie aspekty jak: • możliwość łatwego wykorzystywania wskazówek zapytań, specyficznych dla bazy Oracle, • łatwiejszy dostęp do wywoływania procedur składowanych, • obsługę obiektów przestrzennych, • obsługę wirtualnych, prywatnych baz danych. W zakresie wsparcia w postaci narzędzi programistycznych, podobnie jak w przypadku Hibernate, wiele środowisk ma wbudowaną obsługę EclipseLink (np. JDeveloper) lub istnieją odpowiednie wtyczki dodające taką funkcjonalność. Na architekturze środowiska Eclipse zbudowany jest projekt Web Tools Platform [WTP], którego jeden z elementów stanowi Eclipse Dali – projekt wspierający operacje związane z tworzeniem mapowania obiektowo-relacyjnego przy użyciu JPA i EclipseLink. Biblioteka EclipseLink jest udostępniana na licencji Eclipse Public License. 300 Paweł Boiński 3. Testy wydajnościowe Jednym z istotnych kryteriów przy doborze technologii może być wydajność wybranego rozwiązania. W celu określenia, która z przedstawionych technologii implementacji warstwy dostępu do danych w aplikacjach ADF charakteryzuje się większą efektywnością, przeprowadzono szereg testów wydajnościowych. Ze względu na ograniczoną, maksymalną długość artykułu, przedstawione zostały wybrane wyniki badań. 3.1. Środowisko testowe Do wykonania testów wykorzystano dwie stacje robocze. Parametry obu stacji zostały podane w tab. 1. Na pierwszej stacji zainstalowano bazę danych Oracle 11gR2, natomiast na drugiej uruchomiona była aplikacja ADF. Dzięki takiemu rozwiązaniu zredukowana została możliwość wystąpienia nieprawidłowych odczytów czasów wykonania spowodowana przez aplikacje rywalizujące o zasoby. Stacje robocze zostały połączone łączem o przepustowości 100mbp/s. Przeprowadzone testy obejmowały porównanie technologii ADF Business Components z JPA. W przypadku technologii JPA użyta została implementacja EclipseLink (wersja 2.0.2) oraz Hibernate (wersja 3.2.3). Serwer WebLogic podczas testów działał w trybie produkcyjnym z ograniczonym, do niezbędnego minimum, logowaniem ewentualnych błędów. Tabela 1. Parametry środowiska testowego Stacja robocza 1 Konfiguracja sprzętowa Baza danych Serwer aplikacji Implementacja JPA AMD Phenom X3 2800MHz, 4GB RAM, HDD 500GB 7200RPM Oracle 11g Release 11.2.0.1.0 Stacja robocza 2 Intel Core2Duo 1800MHz, 2GB RAM, HDD 200GB 5400 RPM WebLogic Server 10.3.3.0 EclipseLink 2.0.2 Hibernate 3.2.3 Schemat bazy danych obejmował trzy relacje połączone związkami typu jeden do wiele. W bazie danych znajdowało się 11 mln krotek. Dołożono wszelkich starań, aby testy wykonywane były w tych samych warunkach. Uzyskane wyniki oparte są o średnią otrzymaną z wykonania dziesięciu iteracji każdego z testów. Podczas wszystkich testów parametr fetch size sterownika JDBC (ang. Java Database Connectivity) był ustawiony na wartość 50. Eksperymenty przeprowadzano dla wstawienia/odczytu/modyfikacji/usunięcia od 10000 do 50000 krotek z krokiem co 10000. Przeprowadzone testy obejmowały eksperymenty na obiektach encyjnych oraz obiektach perspektyw dla technologii ADF Business Components (w opisach i na wykresach użyty został skrót od nazwy: ADF BC). W przypadku technologii JPA, testy były wykonane przy użyciu implementacji Hibernate i EclipseLink. Wykorzystane zostały obiekty encji JPA oraz zapytania języka JPQL. 3.2. Opis testów i wyników W kolejnych podpunktach zostały przedstawione opisy przeprowadzonych testów oraz uzyskanych wyników eksperymentów. Analiza porównawcza technologii implementacji warstwy dostępu do danych... 301 3.2.1. Losowy odczyt obiektów Odczyt losowy obiektów, fetch size = 50 90,00 EclipseLink - encje JPA 80,00 Czas wykonania [s] 70,00 60,00 Hibernate - encje JPA Hibernate - JPQL + optymalizacja ADF BC - obiekt encji ADF BC - obiekt perspektywy + optymalizacja ADF BC - obiekt perspektywy 50,00 40,00 30,00 20,00 10,00 0,00 10000 20000 30000 40000 50000 Liczba obiektów Rys. 1. Losowy odczyt obiektów Pierwszy z przeprowadzonych testów obejmował operację odczytu losowo wybranych obiektów z bazy danych. Selekcja była oparta o identyfikator krotki/obiektu. Ze względu na rozmiar danych w bazie danych, przekraczający znacznie liczbę odczytywanych krotek, liczba trafień w pamięć podręczną była znikoma. W ramach testów wykorzystano encje JPA oraz obiekty encji ADF Business Components (standardowe parametry). Do wykonania przetwarzania użyto także: • dla JPA – zapytań JPQL – przeprowadzone badania wykorzystywały polecenia JPQL za- równo bez wskazówek (ang. hints), jak również ze wskazówkami dotyczącymi wykonania zapytań. Użyta wskazówka definiowała przechowywanie w pamięci przygotowanych zapytań (dla Hibernate jest to ustawienie parametru cacheable na wartość true). • dla ADF BC – obiektów perspektyw – w wersji podstawowej obiekt perspektywy zdefinio- wany był na obiektach encyjnych z wyszukiwaniem po identyfikatorze przy wykorzystaniu metody findByPK. Wersja zoptymalizowana (oznaczona na wykresie słowem optymalizacja) zakładała wykorzystanie klauzuli WHERE polecenia SQL zdefiniowanego w obiekcie perspektywy. Wprowadzono do tej klauzuli warunek równościowy na identyfikatorze krotki. Ponieważ każde zapytanie polega na odczycie jednej krotki z bazy danych, metoda odczytu danych z bazy danych przez obiekt perspektywy Retrieve from database, została ustawiona na At most one row. Uzyskane wyniki (patrz rys. 1) wskazują na największa efektywność przy wykorzystaniu obiektów encji (technologia ADF Business Components). Jednocześnie najgorsze wyniki również dotyczę ADF Business Components, jednak przy użyciu obiektów perspektyw. Dla technologii JPA najlepsze wyniki osiągnięto w przypadku użycia encji JPA w implementacji Hibernate, które znacznie wyprzedziły implementację EclipseLink. Na wykresie nie zamieszczono wyników uzyskanych przy wykorzystaniu języka JPQL bez użycia wskazówek. W obu przypadkach (Hiberanate, EclipseLink) uzyskane wyniki tak bardzo odbiegały od pozostałych rezultatów, że wymagałyby użycia innej skali. Na przykład dla technologii Hibernate przy odczycie 20000 obiektów czas wynosił ok. 1500 sekund. Implementacja EclipseLink wykazała się lepszymi wynikami, jednak i tak kilkadziesiąt razy gorszymi niż w przypadku użycia encji JPA. Próba optymalizacji zapytań JPQL dała pozytywne wyniki w ramach poleceń Hibernate. Uzyskany wynik (na wykresie oznaczony jako JPQL + optymalizacja) jest wolniejszy od encji JPA Hibernate, ale szybszy niż encje JPA EclipseLink. Dokonano również optymalizacji (patrz opis eksperymentu) wykonania przy 302 Paweł Boiński użyciu ADF Business Components i obiektów perspektyw. Uzyskany rezultat pozostał jednak nadal gorszy niż konkurencyjne technologie pokazane na wykresie. 3.2.2. Wielokrotny odczyt tego samego elementu Odczyt wielokrotny tego samego elementu w ramach pojedynczej transakcji 2,00 1,80 EclipseLink - encjeJPA Czas wykonania [s] EclipseLink - JPQL - optymalizacja 1,60 Hibernate - encje JPA 1,40 Hibernate - JPQL - optymalizacja ADF BC - obiekt encji 1,20 ADF BC - obiekt perspektywy 1,00 0,80 0,60 0,40 0,20 0,00 10000 20000 30000 40000 50000 Liczba obiektów Rys. 2. Odczyt tego samego elementu w ramach pojedynczej transakcji Celem kolejnego testu było sprawdzenie, jak zachowują się badane rozwiązania w przypadku wielokrotnego odczytu tego samego elementu z bazy danych. W ramach testów wykorzystano encje JPA oraz obiekty encji ADF Business Components (standardowe parametry). Do wykonania przetwarzania użyto także zapytań JPQL. Zbadano standardowe (bez wskazówek) oraz zoptymalizowane zapytania. Dla biblioteki EclipseLink posłużono się wskazówką: @QueryHint(name = QueryHints.CACHE_USAGE, value = CacheUsage.CheckCacheThenDatabase) która jawnie wymusza użycie pamięci podręcznej przed wysłaniem zapytania do bazy danych. W przypadku biblioteki Hibernate wykorzystano następujące wskazówki: @javax.persistence.QueryHint(name = "org.hibernate.cacheable", value = "true"), @javax.persistence.QueryHint(name = "org.hibernate.cacheRegion", value = "tester_region" gdzie tester_region to nazwa przestrzeni pamięci podręcznej implementowanej przez bibliotekę EHCache [EHC]. Wykonanie przy użyciu obiektów perspektyw ADF Business Components przebiegało przy parametrze Retrieve from database ustawionym na wartość At most one row. Uzyskane wyniki (patrz rys. 2) pokazują, że największą szybkością charakteryzują się encje JPA implementowane przez bibliotekę Hibernate. Niemal równie wydajne są encje JPA EclipseLink oraz obiekty encyjne ADF Business Components. Nieco mniejszą szybkość wykazują obiekty perspektyw ADF Business Components oraz zapytania JPQL EclipseLink. Najwolniejsze są zapytania JPQL implementowane przez bibliotekę Hibernate. Należy zauważyć, że we wszystkich opisywanych przypadkach, czas potrzebny na odczyt obiektu jest bardzo mały i w środowisku produkcyjnym będzie miał znikomy wpływ na wydajność aplikacji. Analiza porównawcza technologii implementacji warstwy dostępu do danych... 303 3.2.3. Odczyt zbioru obiektów wraz z obiektami powiązanymi referencją Odczyt zbioru obiektów i referencji, fetch size = 50 120,00 EclipseLink - JPQL EclipseLink - JPQL + optymalizacja 100,00 Hibernate - JPQL Hibernate - JPQL - fetch Czas wykonania [s] ADF BC - obiekty perspektywy 80,00 ADF BC - obiekty perspektywy z połączeniem EclipseLink - JPQL - batch EclipseLink - JPQL - fetch 60,00 Hibernate - JPQL - fetch + optymalizacja 40,00 20,00 0,00 10000 20000 30000 40000 50000 Liczba obiektów Rys. 3. Odczyt zbioru obiektów i obiektów powiązanych referencją Odczyt zbioru obiektów i referencji, fetch size = 50 wybrane, najlepsze strategie 30,00 ADF BC - obiekty perspektywy z połączeniem 25,00 EclipseLink - JPQL - fetch Czas wykonania [s] Hibernate - JPQL - f etch + optymalizacja 20,00 15,00 10,00 5,00 0,00 10000 20000 30000 40000 50000 Liczba odczytów Rys. 4. Odczyt zbioru obiektów i wartości powiązanych referencją, wybrane strategie Kolejny test polegał na odczycie zbioru obiektów za pomocą zapytania z warunkiem nierównościowym (zapytanie o zakres). Jednocześnie odczytywane były zbiory obiektów powiązanych zależnością referencyjną. Zarówno w przypadku JPA, jak również obiektów encji ADF Business Components, nie jest możliwe wykonie zapytania zwracającego zbiór obiektów. Wyniki dotyczą wykorzystania zapytań JPQL oraz obiektów perspektyw. W implementacji EclipseLink, oprócz standardowych zapytań, wykorzystano zapytania (oznaczone na wykresie słowem optymalizacja) wzbogacone o wskazówki: @QueryHint(name = QueryHints.CACHE_USAGE, value = CacheUsage.CheckCacheThenDatabase) W przypadku biblioteki Hibernate słowo optymalizacja oznacza użycie wskazówki: cacheable=true 304 Paweł Boiński Na wykresie pokazane zostały również czasy wykonań dla zapytań JPQL oznaczone słowami: • fetch – powoduje wykonanie operacji połączenia relacyjnego i odczyt danych z obu relacji w pojedynczym zapytaniu, • batch – powoduje odczyt danych z drugiej relacji po odczycie danych z pierwszej relacji. Dla obiektu perspektywy ADF Business Components wartość parametru Retrieve from database ustawiono na All at once (przetestowano również wersję z wartością As needed i parametrem In batches of równym 50, jednak nie zaobserwowano istotnych różnic w czasie wykonania i ze względu na czytelność wykresu nie zamieszczono na nim wyników tego eksperymentu). Dodatkowo zdefiniowano obiekt perspektywy z jawnym połączeniem relacji (oznaczenie na wykresie: ADF BC – obiekt perspektywy z połączeniem). Parametry te nie miały wpływy Uzyskane rezultaty (patrz rys. 3) pozwalają na wyciągnięcie wniosku o przewadze technologii JPA. Obie przetestowane implementacje wykazują lepszą wydajność w stosunku do ADF Business Components. W przypadku braku optymalizacji zapytań JPQL, nieco bardziej wydajna jest implementacja Hibernate, podczas gdy przy optymalizacji rolę lidera przejmuje biblioteka EclipseLink. Zarówno w przypadku JPA, jak również ADF Business Components, wprowadzone optymalizacje znacząco zmniejszają czas wykonania przetwarzania (poprzez ograniczenie liczby wykonywanych zapytań). Należy zauważyć, że zoptymalizowana (z połączeniem) wersja ADF Business Components wygrywa nieznacznie ze standardowymi wykonaniami JPQL z technologii JPA. Na rys. 4 przedstawiono najlepsze wyniki dla każdej z testowanych technologii. 3.2.4. Wstawianie danych Wstawianie danych, batching, liczba obiektów wstawianych w pojedyńczej transakcji = 50 7,00 EclipseLink - encje JPA 6,00 Hibernate - encje JPA Czas wykonania [s] ADF BC - obiekty encji 5,00 ADF BC - obiekty perspektywy 4,00 3,00 2,00 1,00 0,00 10000 20000 30000 40000 Liczba wstawianych obiektów Rys. 5. Wstawianie danych 50000 Analiza porównawcza technologii implementacji warstwy dostępu do danych... 305 Wstawianie danych z generowaniem klucza, batching (50), liczba obiektów wstawianych w pojedyńczej transakcji = 50 160,00 EclipseLink - encje JPA Czas wykonania [s] 140,00 Hibernate - encje JPA ADF BC - obiekty encji 120,00 ADF BC - obiekty perspektyw 100,00 80,00 60,00 40,00 20,00 0,00 10000 20000 30000 40000 50000 Liczba wstawianych obiektów Rys. 6. Wstawianie danych z generowaniem klucza Następny z opisywanych testów dotyczy problemu utrwalania danych w bazie danych. Przetestowane zostały następujące technologie: • obiekty JPA dla technologii EclipseLink i Hibernate (wykorzystano metodę persist klasy EntityManager) przy włączonej opcji hurtowego wykonania operacji DML (ang. batching) odpowiednio poprzez parametry hibernate.jdbc.batch_size dla Hibernate i eclipselink.jdbc. batch-writing dla EclipseLink ustawione na wartość 50, • obiekty encji (metody createInstance klasy EntityDefImpl) i obiekty perspektyw (metody createRow i insertRow klasy Row) dla technologii ADF Business Components. Podczas wykonania testów opcja use batching była włączona. Powoduje ona wykorzystanie możliwości wstawienia wielu krotek przy wykorzystaniu jednego polecania. Nie przeprowadzono testów przy użyciu JPQL, ponieważ język ten nie specyfikuje możliwości użycia polecenia typu insert. Na wykresach pokazano wyniki dla wykonania, w którym w jednej transakcji było utrwalanych 50 obiektów. Przeprowadzono dwa testy w zależności od sposobu generowania wartości identyfikatora: dla jawnie podanej wartości i dla wartości generowanej z sekwencji w bazie danych. Uzyskane wyniki (patrz rys. 5 i rys. 6) pozwalają na stwierdzenie, że najwolniejszą technologią są obiekty perspektyw ADF Business Components. Dotyczy to wstawiania obiektów z i bez generowania klucza. W przypadku wykonania eksperymentu wstawiania krotek bez generowania, klucza najszybszą technologią są obiekty encji ADF Business Components oraz encje JPA w implementacji EclipseLink. Nieco wolniejsze są encję JPA oferowane przez bibliotekę Hibernate. W sytuacji konieczności generowania klucza przez sekwencję zdefiniowaną w bazie danych, najszybszą technologią są encje JPA w implementacji Hibernate, które nieznacznie wyprzedzają encje JPA dostarczane przez EclipseLink oraz obiekty encji z technologii ADF Business Components. 306 Paweł Boiński 3.2.5. Modyfikacja danych 50,00 Modyfikacja danych, 50 modyfikacji na transakcję, batching EclipseLink - encje JPA 45,00 EclipseLink - JPQL Czas wykonania [s] 40,00 Hibernate - encje JPA Hibernate - JPQL 35,00 ADF BC - obiekty encyjne ADF BC - obiekty perspektywy 30,00 25,00 20,00 15,00 10,00 5,00 0,00 10000 20000 30000 40000 50000 Liczba obiektów Rys. 7. Modyfikacja danych, 50 operacji na transakcję Kolejny z przeprowadzonych testów posłużył do zbadania wydajności dostępnych rozwiązań przy modyfikacji obiektów. We wszystkich przypadkach, w przetwarzanych obiektach był zdefiniowany atrybut przechowujący numer wersji zwiększany przy każdej modyfikacji (funkcjonalność oferowana przez badane rozwiązania). Podobnie jak w przypadku wstawiania danych, liczba operacji modyfikacji w pojedynczej transakcji została ustawiona na 50. Scenariusz modyfikacji danych zrealizowano dla następujących technologii: • encje JPA – wykorzystanie metody find klasy EntityManager w celu znalezienia obiektu a następnie modyfikacja obiektu metodą set*, • zapytania JPQL – wykorzystanie polecenia UPDATE języka JPQL z operatorem równo- ściowym. Dla wykonania przy użyciu Hibernate, parametr hibernate.jdbc.batch_size został ustawiony na wartość 50, natomiast dla biblioteki EclipseLink, parametr eclipselink.jdbc.batch-writing na wartość JDBC, a eclipselink.jdbc.batch-writing.size na wartość 50, • obiekty encji – wykorzystanie metody findByPrimaryKey klasy EntityDefImpl do znalezie- nia obiektu, modyfikacja obiektu metodą set* przy włączonej opcji use batching, • obiekty perspektywy – wykorzystanie metody findByKey klasy ViewObjectImpl i modyfika- cja obiektu za pomocą metody set*. Uzyskane wyniki (patrz rys. 7) wskazują na największą wydajność rozwiązania opartego na zapytaniach JPQL w technologii JPA. Obie implementacje, Hibernate i EclipseLink, wykazały się podobną efektywnością. Znacznie wolniejsze są obiekty encyjne z technologii ADF Business Components, które jednak wykonują operację modyfikacji szybciej niż encje JPA. Najwolniejszym rozwiązaniem są obiekty perspektyw ADF Business Components. Analiza porównawcza technologii implementacji warstwy dostępu do danych... 307 3.2.6. Usuwanie danych Uuswanie danych, 50 operacji na transakcję, batching 60,00 EclipseLink - encje JPA EclipseLink - JPQL 50,00 Hibernate - encje JPA Czas wykonania [s] Hibernate - JPQL ADF BC - obiekty encyjne 40,00 ADF BC - obiekty perspektywy 30,00 20,00 10,00 0,00 10000 20000 30000 40000 50000 Liczba obiektów Rys. 8. Usuwanie danych, 50 operacji na transakcję Ostatni z prezentowanych testów badał wydajność operacji usuwania obiektów. Tak jak w poprzednich eksperymentach, liczba operacji modyfikacji w pojedynczej transakcji została ustawiona na 50. Badanie efektywności przeprowadzono dla następujących technologii: • encje JPA – wykorzystanie metody find klasy EntityManager do znalezienia obiektu, a na- stępnie usunięcie tego obiektu za pomocą metody remove klasy EntityManager, • zapytania JPQL – wykorzystanie polecenie delete z warunkiem równościowym języka JPQL. Dla biblioteki Hibernate parametr hibernate.jdbc.batch_size został ustawiony na wartość 50, natomiast dla implementacji EclipseLink parametr eclipselink.jdbc.batchwriting na wartość JDBC, a eclipselink.jdbc.batch-writing.size na wartość 50, • obiekty encji – wykorzystanie metody findByPrimaryKey klasy EntityDefImpl do znalezie- nia obiektu, usunięcie obiektu metodą remove klasy EntityDefImpl przy włączonej opcji use batching, • obiekty perspektywy – wykorzystanie metody findByKey z klasy ViewObjectImp, a następ- nie modyfikacja obiektu metodą remove (interfejs Row). Podobnie jak w przypadku operacji modyfikacji obiektów, operacje usuwania są najszybciej wykonywane przy wykorzystaniu rozwiązania opartego na zapytaniach JPQL w technologii JPA. Obiekty encyjne ADF Business Components są jednak przy usuwaniu niemal tak samo wydajne. Wolniejszym rozwiązaniem jest użycie encji JPA, które dla obu badanych implementacji (Hibernate i EclipseLink) dają niemal identyczne wyniki. Ponownie najwolniejszym rozwiązaniem są obiekty perspektyw dla ADF Business Components. 4. Podsumowanie Opisane w artykule technologie utrwalania danych oferują szereg funkcjonalności potrzebnych programiście przy implementowaniu aplikacji. Autor starał się przestawić cechy charakterystyczne oraz dobre i złe strony omawianych sposobów implementacji warstwy dostępu do danych. Oczywiście niemożliwe jest dokonanie kompletnego przeglądu wszystkich aspektów rozwiązań w ramach tego tekstu. Nadrzędnym celem była analiza wydajności rozpatrywanych technologii. Zarówno ADF Business Components, jak również biblioteki Hibernate i EclipseLink wykazują wysoką wydajność w realizacji operacji odczytu, wstawiania, modyfikacji i usuwania obiektów. 308 Paweł Boiński Za zwycięzcę pod względem wydajności, można uznać bibliotekę Hibernate, której w niewielkim stopniu ustępuje implementacja JPA dostarczona przez EclipseLink. Można podejrzewać, że przy skomplikowanych zapytaniach do bazy danych Oracle, w których wymagana jest optymalizacja dokonywana przez programistę, sytuacja ta mogłaby wyglądać odwrotnie dzięki szerokiemu wsparciu dla tej platformy przez bibliotekę EclipseLink. Dobrą wydajnością cechują się również obiekty encyjne w ramach ADF Business Components, jednak w praktycznym zastosowaniu rzadko korzysta się z tych elementów z pominięciem obiektów perspektyw, które okazały się być najmniej wydajną technologią. Spadek wydajności przy użyciu tych komponentów nie był jednak dramatyczny. Co więcej, z punktu widzenia programisty, ADF Business Components wymagały znacznie mniejszego wkładu w zakresie optymalizacji. Spowodowane jest to bardzo dobrym wsparciem środowiska programistycznego JDeveloper, które udostępnia szereg ustawień dla komponentów biznesowych. Większe nakłady pracy są wymagane przy bibliotekach JPA. Ciekawym aspektem jest również fakt, że podczas eksperymentów, znacznie łatwiej przebiegała optymalizacja dla Hibernate niż dla wywodzącej się z Oracle Toplink biblioteki EclipseLink. W przypadku losowego odczytu obiektu za pomocą JPA, nie udało się dla tej technologii dokonać skutecznej optymalizacji mimo, że takie same działania w środowisku Java SE zakończyło się sukcesem. Przewagą technologii ADF Business Components jest szeroka dokumentacja i integracja ze środowiskiem JDeveloper, które wspiera automatyzację zadań dla tych komponentów. Za wadę można uznać wspomniany już brak wykorzystania POJO i złożoność struktur. Technologia ADF Business Components, mimo wspieranego odwzorowania obiektowo-relacyjnego, znacznie większy nacisk kładzie na relacyjny charakter danych. W przypadku JPA obiektowy charakter aplikacji znajduje się na szczycie listy priorytetów. JPA jest również wspierane przez większość popularnych środowisk programistycznych. Korzystniejszy jest również sposób licencjonowania. Na pytanie, jakiej technologii użyć, bardzo trudno udzielić jednoznacznej odpowiedzi. Najbardziej trafne wdaje się być stwierdzenie: to zależy. Warto podkreślić, że ta konkluzja jest subiektywną oceną autora dokonaną na podstawie eksperymentów z wymienionymi technologiami. W przypadku konstruowania aplikacji, która w istotnym stopniu polega na wizualizacji różnego rodzaju list i formularzy, dobrym rozwiązaniem może być ADF Business Components. W przypadku, gdy występuje bardziej złożone przetwarzanie biznesowe, warto sięgnąć po technologię JPA, która oprócz większego stopnia obiektowości, cechuje się również wyższą wydajnością. Problemem w tym wypadku może być natomiast wybór konkretnego dostawcy implementacji JPA. Teoretycznie ścisłe przestrzeganie standardu JPA powinno pozwolić na bezproblemowe przejście na implementację od jednego dostawcy do drugiego, jednak doświadczenia wyrażane przez programistów na blogach i forach internetowych przeczą tak optymistycznym założeniom. Równie istotna może być konieczność wyjścia poza standardowe funkcjonalności JPA w celu uzyskania najlepszej wydajności. Bibliografia [ADF] Oracle Application Development Framework, http://www.oracle.com/technetwork/developertools/adf/index.html [EHC] EHCache, http://ehcache.org [EJB30] Enterprise JavaBeans, Simplified API, v 3.0. http://java.sun.com/products/ejb [EL] The Eclipse Persistence Services Project, http://www.eclipse.org/eclipselink [HIB] Hibernate: Relational Persistence for Java and .NET, http://www.hibernate.org [HT] Hibernate Tools, http://www.hibernate.org/subprojects/tools.html [JEE] Java EE at a Glance, http://java.sun.com/javaee/index.jsp [JSR220] JSR 220: Enterprise JavaBeans 3.0. [JSR227] JSR 227: A Standard Data Binding & Data Access Facility for J2EE, http://jcp.org Analiza porównawcza technologii implementacji warstwy dostępu do danych... 309 [Ora06] Oracle Application Development Framework Developer’s Guide For Forms/4GL Developers 10g Release 3 (10.1.3.0), 2006. [Ora10a] Oracle® Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework 11g Release 1 (11.1.1)], 2010. [Ora10b] Oracle® Fusion Middleware Java EE Developer's Guide for Oracle Application Development Framework 11g Release 1 (11.1.1), 2010. [WTP] Web Tools Platform, http://www.eclipse.org/webtools/