1.1 Mapowanie klas na tabele

Po zapoznaniu się z JDBC najprawdopodobniej masz wrażenie, że praca z bazą danych z aplikacji Java to nadal przyjemność. A gdybym ci powiedział, że całą tę pracę można wykonać 10 razy łatwiej?

Jaka jest główna zaleta języka SQL? Jest to język deklaratywny - opisuje, co chcemy uzyskać, i nie mówi nic o tym, jak to zrobić. Jak - to jest problem serwera SQL.

To samo podejście można zastosować podczas pracy z bazami danych.

W idealnym świecie moglibyśmy po prostu pisać zapytania SQL do bazy danych, aw odpowiedzi otrzymywalibyśmy gotowe obiekty Java lub kolekcje obiektów Java, gdybyśmy zażądali kilku sztuk.

Cóż mogę powiedzieć, w 2000 roku kilku facetów pomyślało i zdecydowało się napisać własny framework ORM.

ORM to skrót od Object-Relational Mapping i jest zasadniczo mapowaniem obiektów Java na zapytania SQL.

Chłopaki wymyślili bardzo prostą rzecz - każda tabela w bazie danych musi odpowiadać jakiejś klasie w aplikacji Java . W aplikacji Java operujemy obiektami, a te obiekty już wiedzą, jak zapisać się do bazy danych.

Były trzy podejścia do rozwiązania tego problemu i wyglądały one mniej więcej tak:

  1. Obiekt zapisuje się do bazy danych i aktualizuje swoje pola na podstawie informacji z bazy danych.
  2. Obiekt jest w stanie zapisać się do bazy danych, ale nigdy nie inicjuje tej sprawy.
  3. Obiekt zawiera tylko dane, a ktoś zapisuje je do bazy danych i ładuje z bazy danych.

Początkowo dominowało to pierwsze podejście, potem popularne były serwery aplikacyjne i Enterprise Java Beans. Istniała nawet cała klasa komponentów bean zwanych Persistence EJB, które same mogły zapisywać się w bazie danych.

Ale pewnego dnia wszystko się zmieniło...

1.2 Pojawienie się hibernacji

W 2001 roku ukazała się pierwsza wersja frameworka Hibernate. Był to bardzo prosty framework, ale pozwalał na użycie zwykłych „głupich obiektów”, które nie wiedziały nic o tym, jak powinny być przechowywane w bazie danych lub stamtąd ładowane.

Mapowanie pól klas Javy i kolumn w tabeli w bazie danych zostało ustawione za pomocą pliku XML. A czasami były dość masywne. Dobra, kogo ja oszukuję. Były to potężne płótna kodu XML. A sytuację ratował tylko fakt, że 20 lat temu nie było tak gigantycznych baz danych jak teraz.

Ale tak naprawdę najpotężniejszą decyzją było ostateczne oddzielenie obiektu, który ma zostać zapisany w bazie danych, od kodu, który go tam zapisał . To rozwiązanie nie jest do końca oczywiste. Ponieważ zasada enkapsulacji mówi, że obiekt wie najlepiej, jak należy go zapisać i załadować.

A podejście ORM naprawdę łamie tę koncepcję. Klasa danych ujawnia swoją wewnętrzną strukturę, ale operowanie na grupach obiektów różnych typów stało się znacznie łatwiejsze.

Wielki przełom nastąpił po wydaniu Javy 5 , kiedy w JDK pojawiły się dwie rzeczy:

  • Adnotacje
  • pełnomocnik

AdnotacjeXML został szybko wyparty, a teraz łatwo było określić wszystkie niezbędne ustawienia do mapowania klasy Java na tabelę w bazie danych bezpośrednio w klasie Java.

Pełnomocniknie tak zauważalne dla użytkownika Hibernate, ale ich wkład był jeszcze poważniejszy. Kiedy żądasz określonego obiektu lub obiektów z Hibernate, po prostu zwraca ci kod pośredniczący (proxy) i przechwytuje wszystkie wywołania swoich metod.

Umożliwiło to zaimplementowanie różnych mechanizmów Lazy Loading oraz podniosło szybkość i wydajność Hibernate do zupełnie kosmicznego poziomu jak na tamte czasy. Hibernate stał się de facto standardem branżowym – zaczął być tłumaczony na inne języki. I tak na przykład dla C# pojawił się Framework NHibernate.

1.3 Pojawienie się WZP

Po de facto następuje uznanie de iure. Twórcy JDK postanowili stworzyć specyfikację dotyczącą poprawnego mapowania obiektów na tabele w bazie danych. Ta specyfikacja nazywa sięWZP- API trwałości Javy.

To jest właśnie specyfikacja. Opisuje, jak wszystko powinno działać i jakich adnotacji potrzebujemy, aby zaznaczyć różne części klasy, jeśli chcemy, aby jej obiekty zostały zapisane w bazie danych.

Wygląda na to, że chłopaki po prostu wzięli Hibernate jako podstawę i zmienili z niego nazwy pakietów. Ponieważ wszystkie adnotacje, które były w Hibernate, zostały przeniesione do JPA prawie jedna po drugiej.

Dziś Hibernate w pełni implementuje całą specyfikację JPA, a także kilka dodatkowych funkcji, dzięki którym praca z nim jest jeszcze wygodniejsza. Dlatego, jeśli chodzi o standaryzację, możemy powiedzieć, że Hibernate ma dwa zestawy funkcji:

  • norma JPA
  • Hibernate Native API (dodatkowa funkcjonalność)

Oficjalna dokumentacja Hibernate opisuje to w ten sposób:

Ale zarówno na podstawie mojego doświadczenia, jak i po ponownym przeczytaniu dokumentacji Hibernate, mogę powiedzieć, że JPA i Hibernate API są w 95% takie same. To są po prostu identyczne pojęcia.

1.4 Maven dla hibernacji

Ponieważ tak bardzo chwaliłem Hibernate, myślę, że nadszedł czas, aby przejść do trochę cięższej pracy z nim.

Po pierwsze, istnieje oficjalna strona, na której znajduje się tylko garść dokumentacji w języku angielskim. Ona, oczywiście, ma stronniczość w informacjach referencyjnych, a nie w szkoleniu. Ale to wciąż lepsze niż debugowanie źródeł, prawda? :)

Instrukcja:

  1. Otwierasz łącze .
  2. Patrzysz na nią długo.
  3. Wracając do CodeGym.
  4. Czytasz moje dalsze wykłady.

Moim zadaniem jest upraszczanie skomplikowanych rzeczy i wyjaśnianie ich w prosty sposób. A jeśli osiągnąłeś ten poziom, to mogę to zrobić.

Cóż, aby zacząć korzystać z Hibernate, musisz dodać go do pliku pom.xml. Na razie dostępna jest już 6. wersja Hibernate, a raczej 6.1.1, więc nauczymy się pracować z najnowszą wersją.

Po prostu dodaj te linie do pliku pom.xml:


<dependency>
	<groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
	<version>6.1.1.Final</version>
</dependency>

Jeśli czytasz ten wykład poza oknem 2023+, to nową wersję możesz pobrać tutaj .

Ważny! Niektóre biblioteki używane przez Hibernate zostały wycofane z JDK 11 i JDK 17, więc jeśli masz problemy z uruchomieniem projektu, dodaj do niego następujące zależności:


  	<dependency>
        <groupId>jakarta.xml.bind</groupId>
        <artifactId>jakarta.xml.bind-api</artifactId>
      	<version>4.0.0</version>
  	</dependency>
 
  	<dependency>
        <groupId>org.glassfish.jaxb</groupId>
        <artifactId>jaxb-runtime</artifactId>
      	<version>4.0.0</version>
  	</dependency>
 
  	<dependency>
        <groupId>org.javassist</groupId>
        <artifactId>javassist</artifactId>
        <version>3.29.0-GA</version>
  	</dependency>