Hibernate – czy potrzebujesz getterow i setterow?

Czy potrzebujesz akcesorów (getterów i setterów), żeby móc zapisywać i odczytywać modele w Hibernate? Takie pytanie dostałem na jednej z rozmów kwalifikacyjnych… i przyznam szczerze – nie znałem na nie odpowiedzi. Nie miałem pojęcia jak działa Hibernate pod spodem.

W dzisiejszym artykule:


Field vs Property Access

Hibernate – zgodnie ze standardem JPA – oferuje dwa sposoby dostępu do manipulowania obiektem zarządzanym (takim, który posiada adnotację @Entity). Możemy użyć Field-based access lub Property-based access.

Obydwie metody nie wymagają od developera dużego nakładu sił – wystarczy dodać odpowiednią adnotację w klasie którą oddajemy we władanie frameworkowi. W obu przypadkach adnotacja będzie taka sama – @Id. Jaka jest więc różnica?

Field-based access oznacza, że nasze adnotacje znajdują się bezpośrednio nad polami w klasie. Hibernate używa refleksji do odczytu i zapisu danych.

Property-based access natomiast wykorzystuje akcesory (gettery i settery) do dostępu do atrybutów klasy a adnotacje umieszczamy nad getterami atrybutów.


Definiowanie Strategi

Domyślnie strategia jest definiowana na zasadzie – tam gdzie jest adnotacja @Id, taki rodzaj dostępu wybierz. Czyli jeżeli adnotację @Id umieszczasz bezpośrednio nad polem to Hibernate (a w zasadzie to standard JPA) wybierze Field-based access i analogicznie jeżeli umieścisz adnotację nad getterem to zostanie wybrany Property-based access.

W specyfikacji JPA 2.0 pojawiła się nowa adnotacja @Access, która umożliwia łączenie obu technik.


Wydajność – co będzie lepsze?

W kwestii wydajności można by było bazować na tej odpowiedzi ze stackoverflow ale nie jest ona w pełni miarodajna z dwóch powodów:

    1. Zakres danych jest relatywnie mały
    2. Odpowiedź jest stara

Z tych dwóch powodów postanowiłem przeprowadzić własne, bardzo podobne testy. Do tego celu użyłem zbioru danych IMDb – a dokładniej tych 3 tabel:

Wydajność testowałem na tabeli actors która posiada 817 718 rekordów a dodatkowo, żeby ‚skomplikować’ nieco zapytanie, włączyłem jeszcze dociąganie danych z  tabeli roles która u mnie posiada 1 467 257 wpisów (w bazie IMDb jest ich ponad 3 miliony ale nie starczyło mi cierpliwości żeby to wszystko importować).

Zapytanie wyciągające wszystkich aktorów, generowane przez hibernate’a prezentuje się następująco:

W ramach testu pobrałem całą kolekcję aktorów przy użyciu HibernateTemplate. Aby test był bardziej miarodajny, powtarzałem czynność kilka razy po 20-30 pobrań w ramach uruchomienia. Uśrednione wyniki:

Field-based access: 17720 ms.

Property-based access: 17914 ms.

Zbiór danych jest spory i jak widać różnica pomiędzy oboma strategiami dostępu nie jest widoczna. Ba! Nawet stwierdzę, że jej nie ma! W zależności od uruchomienia zdarzało się że to Property-based access był szybszy.


Co wybrać?

Chciałbym zaznaczyć bardzo wyraźnie, że jest to wyłącznie moje zdanie i może być tak, że wybór będzie zależał od wymagań Twojego projektu. Niemniej jednak – moim zdaniem – lepszym wyborem w większości sytuacji będzie Field-based access.

Oto 4 powody dlaczego:

  1. Czytelność kodu – wszystkie adnotacje masz zgrupowane razem przy definicji pól. Nie musisz przewijać po całej klasie aby zobaczyć czy aby na pewno dany atrybut posiada adnotację.
  2. Enkapsulacja danych – używając Field-based access nie musisz udostępniać wszystkich akcesorów – używasz tylko tych, które realnie potrzebujesz w aplikacji. W przeciwnym wypadku musisz udostępnić wszystko, tak aby framework mógł sobie poradzić z mapowaniem, pomimo, że sam, w kodzie biznesowym nie potrzebujesz dostępu do pól.
  3. Brak konieczności użycia adnotacji @Transient na metodach utility (np. addChild/removeChild).
  4. Uniknięcie bugów z niezainicjowalnymi encjami ładowanymi przez lazy-loading – odsyłam Cię do tego artykułu po więcej informacji.

Podsumowanie

Hibernate implementuje obie strategie dostępu do atrybutów encji zgodnie ze standardem JPA. To, którą opcję wybierzemy zależy od nas – developerów. Oczywiście zawsze na początku należy kierować się kontekstem w jakim się znajdujesz ale mając z tyłu głowy, że Field-based access jest bardziej przyjazny oraz pozwala uniknąć błędów.

A odpowiadając na pytanie z samego początku – czy potrzebujesz akcesorów, żeby móc zapisywać i odczytywać modele w Hibernate? Odpowiedź brzmi: nie. Hibernate poradzi sobie refleksją 🙂

Źródła:


Za tydzień

Przejdziemy na płaszczyznę architektury oprogramowania i pogadamy o modelach domenowych. Anemic vs Rich Domain Model.

5 1 vote
Article Rating
Subscribe
Powiadom o
guest
0 komentarzy
Inline Feedbacks
View all comments