Przewodnik – pierwsze kroki z Hibernate

Transkrypt

Przewodnik – pierwsze kroki z Hibernate
Jarosław Henke, 6 kwietnia 2016r
Przewodnik – pierwsze kroki
z Hibernate
Na podstawie docs.jboss.org dla Hibernate wersja 5.1 - tłumaczenie i skrót
Stan wiedzy z dnia: 2016-02-11 14:23:58 CST
Spis Treści
Spis Treści.............................................................................................................................2
Wstęp.....................................................................................................................................3
1. Pozyskiwanie Hibernate................................................................................................4
1.1. Moduły Hibernate...................................................................................................4
1.3. Zawartość repozytorium Maven..........................................................................5
2. Używanie rodzimych interfejsów programistycznych (API) Hibernate z
mapowaniem hbm.xml......................................................................................................6
2.1. Plik konfiguracyjny Hibernate..............................................................................6
2.2. Klasa encji Java.........................................................................................................7
2.3. Plik mapujący...........................................................................................................7
2.4. Przykładowy kod.....................................................................................................9
3. Używanie rodzimego Hibernate API z Annotation Mappings............................10
3.1. Plik konfiguracyjny Hibernate............................................................................10
3.2. Klasa encji Javy opatrzona przypisami (annotated entity Java class).........................10
3.3. Przykładowy kod...................................................................................................11
4. Używanie Java Persistence API (JPA).........................................................................12
4.1. persistence.xml.....................................................................................................12
4.2. Klasa encji z przypisami.......................................................................................12
4.3. Przykładowy kod...................................................................................................12
5. Użycie Envers.................................................................................................................13
5.2. 4.2. Klasa encji Java z przypisami........................................................................13
5.3. Przykładowy kod...................................................................................................14
22
Wstęp
Praca jednocześnie z oprogramowaniem zorientowanym obiektowo w połączeniu z relacyjnymi
bazami danych może nie być zbyt wygodna i pochłaniać zbyt wiele czasu. Wpływa na to
niedopasowanie paradygmatów miedzy obiektową reprezentacją danych w stosunku do
relacyjnych baz danych. Przekłada się to bezpośrednio na koszty produkcji, bo przecież czas to
pieniądz. Hibernate – framework typu ORM (Object/Relational Mapping) jest jednym z
najpopularniejszych rozwiązań tego problemu w środowisku Java. Pojęcie Obiect/Relational
Mapping nawiązuje do metody sporządzenia powiązań (mapowania) pomiędzy modelem
reprezentacji obiektowej w obiektach Javy, a modelem relacyjnym w bazach danych.
Pomimo, że posiadanie gruntownego przygotowania w zakresie SQL nie jest wymagane, by
używać Hibernate, to jednak podstawowa wiedza w tym zakresie pomaga zrozumieć Hibernate
szybciej i bardziej w pełni. Znajomość zasad modelowania danych jest tu szczególnie ważna.
Hibernate troszczy się o mapowanie obiektów z klas Javy do tabel bazodanowych dbając też o
mapowanie typów danych z Javy do SQL. W dodatku dostarcza zapytań bazodanowych i
funkcji wyszukiwania danych. To znacznie redukuje czas pracy programisty, który w
przeciwnym wypadku musiałby ręcznie tworzyć zapytania za pomocą SQL-a i JDBC. Celem
projektowym Hibernate jest zwolnienie developera z 95% koniecznych zadań dotyczących
programowania trwałości obiektów, poprzez wyeliminowanie potrzeby fizycznego sklejania
zapytań i używania SQL w połączeniu z JDBC. Jednakże w odróżnieniu od wielu innych
rozwiązań tego typu Hibernate nie rezygnuje z mocy SQL-a. Nie ukrywa możliwości
skorzystania z tej technologii przez programistę i czyni ją dostępną i ważną jak zawsze.
Hibernate może nie jest najlepszym rozwiązaniem dla data-centrycznych aplikacji, w których
cała logika biznesowa sprowadza się do używania jedynie procedur składujących. Jest bardziej
użyteczny w zastosowaniach z modelami domen zorientowanymi obiektowo w logice
biznesowej Javy warstwy środkowej. Z pewnością jednak Hibernate w sposób oczywisty
pozwala na usunięcie lub skrócenie kodu specyficznego dla klienta SQL, usprawniając bieżące
zadanie translacji wyniku zapytania z reprezentacji tabelarycznej do grafu obiektów.
33
1. Pozyskiwanie Hibernate
1.1. Moduły Hibernate
Funkcjonalność Hibernate jest podzielona na pewną ilość niezależnych, wyizolowanych
modułów.
hibernate-core
Główny moduł (jądro) Hibernate. Definiuje jego funkcje ORM oraz interfejsy
programowe aplikacji (Apis) jak również różne interfejsy SPI (Sernice Provider
Interface) zintegrowane z jądrem.
hibernate-entitymanager
Definiuje wsparcie Hibernate dla JPA
hibernate-java8
Wsparcie dla platformy Java8 stosującej specyficzne typy danych takich jak JSR 310
Date/Time w modelu dziedziny.
hibernate-envers
Historyczne wersjonowanie encji Hibernate.
hibernate-spatial
Wsparcie Hibernate dla danych typu Spatial/GIS.
hibernate-osgi
Wsparcie Hibernate do uruchamiania w kontenerach OSGi.
hibernate-c3p0
Integruje bibliotekę połączeń współdzielonych C3P0 z Hibernate.
hibernate-hikaricp
Integruje bibliotekę połączeń współdzielonych HikariCP z Hibernate.
hibernate-proxool
Integruje bibliotekę połączeń współdzielonych Proxool z Hibernate.
44
hibernate-ehcache
Integruje bibliotekę keszującą Ehcache z Hibernate jako dostawcę kesza drugiego
poziomu.
hibernate-infinispan
Integruje bibliotekę keszującą Infinispan z Hibernate jako dostawcę kesza drugiego
poziomu.
1.2. Pobieranie paczek instalacyjnych
Zespół Hibernate umieścił pakiety instalacyjne w systemie SourceForge w formatach TGZ i
ZIP. Każda z paczek zawiera pliki JAR, dokumentację, kody źródłowe i inne dobrodziejstwa.
Pakiety znajdują się pod adresem: https://sourceforge.net/projects/hibernate/files/hibernateorm/. Ich struktura przedstawia się w sposób następujący:
lib/required/ katalog zawierający hibernate-core jar i wszystkie potrzebne pliki
zależne. Wszystkie te jar-y są niezbędne niezależnie od tego, która z funkcjonalności
Hibernate będzie używana.
lib/jpa/ katalog zawierający hibernate-entitymanager jar jak również
wszystkie zależności (uzupełniające te w lib/required/)
lib/java8/ katalog zawierający hibernate-java8 jar jak również wszystkie
zależności (uzupełniające te w lib/required/)
lib/envers katalog zawierający hibernate-envers jak również wszystkie
zależności (uzupełniające te w lib/required/ i lib/jpa/).
lib/spatial/ katalog zawierający hibernate-spatial jar jak również wszystkie
zależności (uzupełniające te w lib/required/)
lib/osgi/ katalog zawierający hibernate-osgi jar jak również wszystkie
zależności (uzupełniające te w lib/required/ i lib/jpa/)
lib/optional/ katalog zawierający pliki typu jar potrzebne do różnych połączeń
wspólnych oraz integracji keszu drugiego poziomu udostępnianego przez Hibernate,
wraz z ich zależnoścami.
1.3. Zawartość repozytorium Maven
Autoryzowanym repozytorium produktów Hibernate jest repozytorium JBoss Maven. Produkty
Hibernate są zsynchronizowane z centralą Maven niejako automatycznie (małe przerwy mogą
się zdarzyć).
Zespół odpowiedzialny za repozytorium JBoss Maven utrzymuje szereg stron typu Wiki, które
zawierają ważne i przydatne informacje.
http://community.jboss.org/docs/DOC-14900 - ogólne informacje o repozytorium.
55
http://community.jboss.org/docs/DOC-15170 - Informacje o instalowaniu repozytoriów
JBoss w celu udziału w rozwoju projektu.
http://community.jboss.org/docs/DOC-15169 - Informacje o zainstalowaniu dostępu do
repozytorium w celu uzyia projektów JBoss jako części swojego wlasnego
oprogramowania.
Produkty Hibernate ORM są publikowane w domenie grupy org.hibernate .
2. Używanie rodzimych interfejsów
programistycznych (API)
Hibernate z mapowaniem
hbm.xml
2.1. Plik konfiguracyjny Hibernate
W tym tutorialu, plik hibernate.cfg.xml definiuje informacje konfiguracyjne Hibernate.
Elementy connection.driver_class, connection.url, connection.username oraz
connection.password <property/> zawierają informacje niezbędne do ustanowienia
połączenia JDBC. Ten samouczek wykorzystuje bazę danych H2 in-memory, zatem wartości
tych własności są właściwe dla prawidłowego działania H2 w trybie in-memory.
connection.pool_size jest używane do konfiguracji liczby połączeń wbudowanych w pulę
połączeń Hibernate.
Wbudowana pula połączeń Hibernate nie służy w żadnym wypadku do użytku produkcyjnego.
Brakuje w niej kilku cech znajdujących się w production-ready connection pools.
Właściwość dialect specyfikuje odpowiedni wariant SQL współpracujący z Hibernate.
W większości przypadków, Hibernate jest zdolne do wykrycia który rodzaj dialektu jest
używany. Jest to szczególnie przydatne jeśli celem aplikacji jest jednocześnie wiele baz
danych.
Własność hbm2ddl.auto umożliwia automatyczną generację schematu bazy bezpośrednio do
bazy danych.
Na końcu do konfiguracji dodawane są pliki mapujące klasy trwałości. Atrybut resource
elementu <mapping/> powoduje, iż Hibernate podejmuje próbę zlokalizowania tego
mappingu używając zasobu tej ścieżki w wyszukiwaniu java.lang.ClassLoader.
66
Jest wiele dróg i opcji do załadowania SessionFactory w Hibernate. Aby poznać więcej
szczegółów, patrz wskazówka Natywny Bootstrapping.
2.2. Klasa encji Java
Przykładowa klasa encji w tym tutorialu znajduje się na stronie
org.hibernate.tutorial.hbm.Event
Notatki dotyczące klasy encji
W tej klasie wykorzystywany jest standard JavaBean w zapisie getterów i setterów, jak
również dostępność pól ustawiona jest na private. Aczkolwiek jest to jedynie zalecane
postępowanie, nie jest koniecznie wymagane.
Konstruktor bezargumentowy, który jest także w konwencji JavaBean, jest wymogiem
dla wszystkich klas trwałości. Hibernate potrzebuje go do stworzenia obiektów za
ciebie, używając Java Reflection. Konstruktor powinien być private. Aczkolwiek,
pakiet lub widoczność public jest wymagana do generowania runtime proxy i
wydajnego wyszukiwania danych bez inkrementacji kodu binarnego.
2.3. Plik mapujący
Przykładowy plik mapujacy dla tego tutorialu
org/hibernate/tutorial/hbm/Event.hbm.xml.
znajduje
się
w
zasobach
Hibernate używa metadanych mapujących by określić w jaki sposób ładować i składować
obiekty klas trwałości. Plik mapujący Hibernate jest jedynym sposobem dostarczenia
środowisku Hibernate tych metadanych.
Przykład 1. Mapowanie klasy
<class name="Event" table="EVENTS">
...
</class>
Funkcje zawierające <varname>class</varname> mapujące element
Atrybut name (w kombinacji z atrybutem package z elementu zawierającego
<hibernate-mapping/>) jest kwalifikowaną nazwą (FQN) klasy definiującej encję.
Atrybut table jest nazwą tabeli bazodanowej, która zawiera dane odpowiadające tej
encji.
Instancje klasy Event są teraz zamapowane do wierszy tabeli bazodanowej EVENTS.
Przykład 2. mapowanie id
<id name="id" column="EVENT_ID">
...
</id>
Hibernate używa właściwości nazwanej jako <id/> do unikatowej identyfikacji wierszy w
tabeli.
77
Element id nie jest potrzebny do mapowania kolumny klucza głównego tabeli ale jest to
normalna konwencja. Tabele mapowane w Hibernate nie potrzebuja nawet definiowania
kluczy głównych. Jednakże jest to mocno zalecane w celu właściwego zdefiniowania
więzów integralności. Dlatego id i klucz główny są używane wymiennie w całej
dokumentacji Hibernate
Element <id/> tu nazwany jako kolumna EVENT_ID jako klucz główny tabeli EVENTS. To
także okresla własność id klasy Event jako własność zawierającą wartość identyfikatora.
Element generator informuje Hibernate o tym która strategia jest używana do generowania
wartości klucza głównego dla tej encji. Nasz przykład używa prostej inkrementacji.
Przykład 3. Mapowanie właściwości
<property name="date" type="timestamp" column="EVENT_DATE"/>
<property name="title"/>
Dwa zadeklarowane elementy <property/> są związane z dwoma trwałymi właściwościami
klasy Event: date i tittle. Mapowanie właściwości date zwiera atrybut column, ale w
przypadku właściwości tittle już tak nie jest. W przypadku nieobecności atrybutu column,
Hibernate użyłoby nazwy właściwości jako nazwy kolumny. To byłoby odpowiednie dla
właściwości tittle, ale przecież słowo date jest zarezerwowane w większości baz danych i
potrzebne jest przypisanie niezarezerwowanego słowa do nazwy kolumny.
Mapowaniu tytułu brakuje tez atrybutu typu. Typy deklarowane i używane w plikach
mapujących nie są żadnymi typami języka Java ani typami znanymi z SQL-owych baz danych.
Zamiast nich mamy specjalne Hibernate mapping types, które są konwerterami tłumaczącymi
typy pomiędzy Javą a SQL-em. Hibernate samodzielnie decyduje o właściwej konwersji i
mappingu jeśli nie zostały one wyspecyfikowane. Używa tu odwzorowania Javy do
wyznaczenia typu Javy dla zadeklarowanej właściwości i następnie standardowego typu
mapowania dla tego typu Javy.
W niektórych przypadkach automatyczna detekcja może nie przynieść wyboru właściwego lub
oczekiwanego, jak to widac w przypadku właściwości date. Hibernate nie jest w stanie
rozstrzygnąć czy właściwość typu java.util.Date powinna być zamapowana do SQLowego typu danych DATE, TIME czy TIMESTAMP. Pełna informacja o dacie i czasie jest
zabezpieczona przez mapowanie właściwości konwertera timestamp, który identyfikuje klasę
org.hibernate.type.TimestampType.
Hibernate ustala typy mapujące używając odwzorowania w czasie przetwarzania plików. Ta
czynność wydłuża czas mapowania. Jeśli zatem czas wykonania startu jest ważny, należy
rozważyć zdefiniowanie używanych typów.
88
2.4. Przykładowy kod
Klasa org.hibernate.tutorial.hbm.NativeApiIllustrationTest ilustruje użycie
Hibernate native API.
Przykłady w tym tutorialu są przedstawione jako testy jednostkowe JUnit, w celu
uproszczenia. Korzyścią płynącą z takiego rozwiązania jest pokazanie z grubsza za pomocą
setUp i tearDown jak org.hibernate.SessionFactory jest tworzona przy starcie i
zamykana na końcu cyklu życia aplikacji.
Przyklad 4. Uruchamianie org.hibernate.SessionFactory
protected void setUp() throws Exception {
// A SessionFactory is set up once for an application!
final StandardServiceRegistry registry = new
StandardServiceRegistryBuilder()
.configure() // configures settings from
hibernate.cfg.xml
.build();
try {
sessionFactory = new MetadataSources( registry
).buildMetadata().buildSessionFactory();
}
catch (Exception e) {
// The registry would be destroyed by the SessionFactory,
but we had trouble building the SessionFactory
// so destroy it manually.
StandardServiceRegistryBuilder.destroy( registry );
}
}
Na początku metoda setup buduje instancję
org.hibernate.boot.registry.StandardServiceRegistry, która włącza informacje
konfiguracyjne do roboczego setu usług używanego przez SessionFactory. W tym tutorialu
zdefiniowano wszystkie informacje konfiguracyjne w pliku hibernate.cfg.xml zatem nie
ma tu nic więcej do dodania.
Używając StandardServiceRegistry tworzymy org.hibernate.boot.MetadataSourc
es który jest punktem startowym informujacym Hibernate o modelu jego dziedziny. Ponownie,
z powodu zdefiniowania tego w pliku hibernate.cfg.xml nie ma tu nic więcej do dodania.
org.hibernate.boot.Metadata reprezentuje kompletny, częściowo validowalny widok
modelu dziedziny aplikacji na którym będzie bazować SessionFactory.
Ostatnim krokiem w procesie bootstrapu jest zbudowanie SessionFactory.
SessionFactory jest obiektem bezpiecznego wątku, który raz zapoczątkowany jest w stanie
obsłużyć całą aplikację. Akty działania
SessionFactory będące instancjami
org.hibernate.Session powinny być traktowane jak „jednostki pracy”.
99
Przyklad 5. Zapisywanie encji
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save( new Event( "Our very first event!", new Date() ) );
session.save( new Event( "A follow up event", new Date() ) );
session.getTransaction().commit();
session.close();
testBasicUsage() na początku tworzy nowe obiekty Event i zleca im poprzez Hibernate
jako zarządcy użycie metody save().
Hibernate w tym momencie przejmuje
odpowiedzialność za wykonanie INSERT do bazy danych dla każdej instancji Event.
Przyklad 6. Uzyskiwanie listy encji
session = sessionFactory.openSession();
session.beginTransaction();
List result = session.createQuery( "from Event" ).list();
for ( Event event : (List<Event>) result ) {
System.out.println( "Event (" + event.getDate() + ") : " +
event.getTitle() );
}
session.getTransaction().commit();
session.close();
Tutaj widzimy przykład użycia języka HQL (Hibernate Query Language) do załadowania z
bazy danych wszystkich istniejących obiektów Event poprzez wygenerowanie odpowiedniego
zapytania SELECT SQL, wysłania go do bazy danych i umieszczeniu obiektów Event w secie
danych wynikowych.
3. Używanie rodzimego Hibernate
API z Annotation Mappings
3.1. Plik konfiguracyjny Hibernate
Zawartość pliku jest identyczna jak w poprzednim przypadku z jedna ważną różnicą... Element
<mapping/> na samym końcu nazywa przypisaną klasę encji opatrzona przypisami (annotated
entity class) używając atrybutu class.
3.2. Klasa encji Javy opatrzona przypisami (annotated
entity Java class)
W tym tutorialu omawiana klasa encji która przestrzega konwencji JavaBean
to: org.hibernate.tutorial.annotations.Event . Faktem jest, że ta klasa sama w sobie
jest identyczna z klasą encji Javy, tyle tylko że zamiast odrębnego pliku do ustanowienia
metadanych są wykorzystywane przypisy.
10
Przykład 7. Identyfikowanie klasy jako encji
@Entity
@Table( name = "EVENTS" )
public class Event {
...
}
Przypis @javax.persistence.Entity jest używany do zaznaczenia że dana klasa jest encją.
Funkcjonuje to tak samo jak w przypadku tagu mapującego <class/> omawianego przy okazji
plików mapujących. Dodatkowo przypis @javax.persistence.Table wyraźnie określa nazwę
tabeli. Bez tego, defaultywna nazwa tabeli byłaby EVENT.
Przykład 8. Identyfikowanie własności identyfikatora
@Id
@GeneratedValue(generator="increment")
@GenericGenerator(name="increment", strategy = "increment")
public Long getId() {
return id;
}
@javax.persistence.Id zaznacza właściwość, która określa identyfikator encji.
@javax.persistence.GeneratedValue i @org.hibernate.annotations.GenericGen
erator pracują wspólnie, by wskazać, że Hibernate powinno użyć swojej strategii
generowania increment dla tej tak oznaczonych wartości identyfikatorów encji.
Przykład 9. Identyfikowanie własności podstawowych
public String getTitle() {
return title;
}
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "EVENT_DATE")
public Date getDate() {
return date;
}
Jak w
<<hibernate-gsg-tutorial-basic-mapping, własność date wymaga specjalnego
traktowania w celu zarejestrowania jej specjalnej nazwy i typu SQL. Atrybuty encji są uważane
za domyślnie trwałe, oto dlaczego nie widzimy jakichkolwiek informacji powiązanych z
tittle.
3.3. Przykładowy kod
org.hibernate.tutorial.annotations.AnnotationsIllustrationTest jest
zasadniczo taki sam jak org.hibernate.tutorial.hbm.NativeApiIllustrationTest
co jest omówione w http://docs.jboss.org/hibernate/orm/5.1/quickstart/htm
l_single/#hibernate-gsg-tutorial-basic-test.
11
4. Używanie Java Persistence API
(JPA)
4.1. persistence.xml
Poprzednie tutoriale używały specyficznego dla Hibernate pliku konfiguracyjnego
hibernate.cfg.xml. JPA jednakże, określa inny proces bootstrapowy, który używa
własnego pliku konfiguracyjnego o nazwie persistence.xml. Ten proces bootstrapowy jest
określony przez specyfikacje JPA. W środowisku Java™ SE zarządca trwałości (W tym
przypadku Hibernate) musi zlokalizować wszystkie pliki konfiguracyjne wyszukując ich
ścieżek w zasobie META-INF/persistence.xml.
Przykład 10. persistence.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="org.hibernate.tutorial.jpa">
...
</persistence-unit>
</persistence>
Pliki persistence.xml powinny dostarczać unikalnej nazwy każdej jednostce trwałości.
Aplikacje używaja tych nazw do uzyskania referenci do konfiguracji kiedy uzyskują referencję
do javax.persistence.EntityManagerFactory .
Ustawienia zdefiniowane w elemencie <properties/> są omawiane w Plik konfiguracyjny
Hibernate. Tutaj używa sięjavax.persistence -z różnymi odmianami prefiksów w razie
potrzeby. Zauważ że pozostawione specyficzne dla ustawień konfiguracyjnych Hibernate
nazwy maja teraz prefix hibernate..
Dodatkowo, funkcje elementu <class/> podobnie są zapisane w Plik Konfiguracyjny
Hibernate.
4.2. Klasa encji z przypisami
Encje są dokładnie takie same jak te opisane w rozdziale 3.2. Klasa encji Javy opatrzona
przypisami (annotated entity Java class).
4.3. Przykładowy kod
Poprzednie tutoriale używały Hibernate native APIs. Ten tutorial uzywa JPA APIs.
12
Przykład 11. Dostęp do javax.persistence.EntityManagerFactory
protected void setUp() throws Exception {
entityManagerFactory = Persistence.createEntityManagerFactory(
"org.hibernate.tutorial.jpa" );
}
Zauważ ponownie, że nazwa jednostki trwałości to org.hibernate.tutorial.jpa, która
pasuje do persistence.xml.
Przykład 12. Saving (utrwalanie) encji
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
entityManager.persist( new Event( "Our very first event!", new Date() ) );
entityManager.persist( new Event( "A follow up event", new Date() ) );
entityManager.getTransaction().commit();
entityManager.close();
Kod podobny do: Przykład 5. Zapisywanie encji.
Interfejs javax.persistence.EntityManager jest używany zamiast interfejsu
org.hibernate.Session. JPA nazywa tą operację "persist" zamiast "save".
Przykład 13. Dostęp do listy encji
entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
List<Event> result = entityManager.createQuery( "from Event", Event.class
).getResultList();
for ( Event event : result ) {
System.out.println( "Event (" + event.getDate() + ") : " +
event.getTitle() );
}
entityManager.getTransaction().commit();
entityManager.close();
Znowu, kod całkiem podobny do tego który jest zapisany w Przykład 6. Uzyskiwanie listy
encji.
5. Użycie Envers
5.1. persistence.xml
Ten plik był omawiany w rozdziale 4. Używanie Java Persistence API (JPA), a dokładnie
w podrozdziale dotyczącym persistence.xml i jest dokładnie taki sam.
5.2. 4.2. Klasa encji Java z przypisami
Ponownie, the encja jest w większości tym samym co w rozdziale 4.2 Klasa encji Java z
przypisami. Główna różnica polega na dodaniu przypisu
13
@org.hibernate.envers.Audited, który informuje Envers by automatycznie śledził
zmiany w tej encji.
5.3. Przykładowy kod
Kod zapisuje jakieś encje, wprowadza zmianę w jednej z encji a następnie używa Envers API
do cofnięcia początkowej korekcie jak również uaktualnionej korekcie. Korekta odsyła do
historycznej migawki encji.
Example 14. Using the org.hibernate.envers.AuditReader
public void testBasicUsage() {
...
AuditReader reader = AuditReaderFactory.get( entityManager );
Event firstRevision = reader.find( Event.class, 2L, 1 );
...
Event secondRevision = reader.find( Event.class, 2L, 2 );
...
}
Widzimy, że org.hibernate.envers.AuditReader
org.hibernate.envers.AuditReaderFactory,
javax.persistence.EntityManager.
jest wyprodukowany przez
który
opakowuje
Następnie, metoda find odzyskuje dokładne zmiany encji. Pierwsze wywołanie nakazuje
znaleźć korektę nr 1 elementu Event, w którym id = 2. Drugie wywołanie nakazuje znaleźć
korektę nr 2 elementu Event w którym id = 2.
14

Podobne dokumenty