poniedziałek, 8 grudnia 2008

Obiekty Hibernate

Obiekty Hibernate

1. Obiekty sesji

  • Configuration – klasa ta wykorzystywana jest do odczytywania i ustawiania szczegółów implementacyjnych, w Hiberante wykorzystywany jest obiekt tej klasy do utworzenia obiektów typu SessionFactory. Aplikacja posiada jeden obiekt Configuration, który jest wykorzystywany jedynie podczas inicjalizacji.
  • SessionFactory – wykorzystywany jest obiekt tej klasy do tworzenia obiektu Session jeśli zachodzi taka potrzeba. Aplikacja powinna wykorzystywać jeden obiekt Hibernate’a SessionFactory dla każdego osobnego egzemplarza bazy danych. Jest on uzależniony od parametrów konfiguracyjnych Hibernate’a.
  • Session – Za każdym razem gdy aplikacja będzie chciała pracować z bazą danych zostanie utworzony obiekt Session. Aplikacja mam możliwość pobrania obiektu, zmiany niektórych jego własności, a następnie utrwalenia go oraz zamknięcia obiektu Session.

Przykład utworzenia obiektów Hibernate:

SessionFactory sessions =

new Configuration().configure().buildSessionFactory();

Session session = sessions.openSession();

Metoda configure() zwraca egzemplarz obietku Configuration, który może być wykorzystywany do uzyskania egzemplarza Hibernate’a SessionFactory poprzez wywołanie metody buildSessionFactory().

2. Cykl życia obiektu trwałego

Hibernate definiuje tylko 3 stany w cyklu życia obiektu stałego: ulotny (ang. transient), trwały (ang. persistent) i odłączony (ang. detached).

2.1 Obiekty trwałe

Obiekty trwałe istnieją w bazie danych, a ich stan jest synchronizowany z bazą danych na końcu transakcji. Takie obiekty zawsze są związane z obiektem Session. Stan obiektu trafia do bazy w wyniku wykonania operacji takich jak: INSERT, UPDATE, DELETE. Narzędzie Hibernate automatycznie sprawdza, w których obiektach trwałych doszło do zmiany, aby móc później zapisać te dane. Dzięki temu tylko część danych podlega modyfikacji, co pozwala zwiększyć wydajność, przynajmniej w niektórych bazach danych.

2.2 Obiekty odłączone

Obiekty odłączone posiadają swoją reprezentacje w bazie danych ale zmiany w tym obiekcie nie zostaną odzwierciedlone w bazie i na odwrót. Można je stworzyć na dwa sposoby: poprzez zamknięcie sesji z nim powiązanej albo przez usunięcie go z sesji dzięki wywołaniu metody evict(). Są jednak one bardzo użyteczne w momencie gdy chcemy zwrócić obiekt z jednej transakcji do warstwy prezentacji i ponownie użyć go w innej transakcji.

2.3 Obiekty ulotne (przejściowe)

Obiekty ulotne nie są związane z żadnym wierszem bazy danych. Tym samym nie są obsługiwane przez Hibernate. Można je utworzyć przy pomocy operatora new.

3. Metody obiektu Session

· save

Metoda save służy do zmiany obiektu ulotnego w trwały. Metoda save wiąże obiekt z sesją i czyni go trwałym. Obiekt sesji łączy się z bazą danych przy pomocy połączenia JDBC dopiero w momencie zatwierdzenia transakcji .

· update, lock

Metoda update wymusza aktualizację stanu obiektu trwałego w bazie danych. Przy jej pomocy wykonywane jest poleceni UPDATE na bazie danych. Polecenie update wykonuje się na obiektach odłączonych, które można przyłączyć do nowej sesji. Podobnie zachowuje się również polecenia lock. Z tą różnicą że lock wiąże obiekt odłączony z sesją, ale nie wymaga jego aktualizacji w bazie danych.

· saveOrUpdate

Metoda saveOrUpdate powoduje dodanie nowego wiersza w bazie danych jeśli obiekt jest ulotny lub aktualizację jeśli obiekt jest odłączony.

· get

Metoda interfejsu Session służy do pobrania obiektu (np. na podstawie identyfikatora) z bazy danych . Tak powstały obiekt można używać poza transakcją jako obiekt odłączony.

· delete

Metoda delete wywoła polecenie DELETE z SQL ale dopiero w momencie synchronizacji sesji.

...

Źródła: Hibernate w akcji Christian Bauer, Gavin King

niedziela, 23 listopada 2008

Odwzorowanie dziedziczenia przykład

Na początek diagram:


Jak widać mamy tu dziedziczenie, relację wiele do wiele jak i asocjację skierowaną.

Schemat takiej bazy danych może wyglądać następująco:

create table works (

id NUMBER not null primary key,

tempo NUMBER,

genre VARCHAR2(255),

peges NUMBER(4),

title VARCHAR2(255)

);

create table author_work (

author_id NUMBER not null,

work_id NUMBER not null,

primary key (work_id, author_id)

);

create table authors (

id NUMBER not null primary key,

alias VARCHAR2(255)

);

create table persons (

id NUMBER not null primary key,

name VARCHAR2(255)

);

alter table authors

add constraint authorsFK0 foreign key (id) references persons;

alter table author_work

add constraint author_workFK0 foreign key (author_id) references authors;

alter table author_work

add constraint author_workFK1 foreign key (work_id) references works;

Czyli został zastosowany drugi schemat odwzorowania dziedziczenia klas na tabele, mianowicie tabela na każdą hierarchie klas. Z trzech klas (Work, Song, Book) powstała jedna tabela works.

Problem asocjacji wiele do wiele został rozwikłany dodaniem tabeli łączącej autor_work. Ale teraz najważniejsza część: jak Hibernate wygenerował klasy oraz pliki mapujące na podstawie tego schematu bazy.

Klasa Works:

public class Works implements java.io.Serializable {


private BigDecimal id;

private BigDecimal tempo;

private String genre;

private Short peges;

private String title;

private Set authorses = new HashSet(0);

….

//konstruktory, settery , gettery

}

Klasa Authors:

public class Authors implements java.io.Serializable {


private BigDecimal id;

private Persons persons;

private String alias;

private Set workses = new HashSet(0);

}

Klasa Persons

public class Persons implements java.io.Serializable {


private BigDecimal id;

private String name;

private Set authorses = new HashSet(0);

}

Nic tu zaskakującego na razie nie ma poza tym, że nie została zaimplementowana Klasa AuthorWork na podstawie tabeli author_work. Jak więc Hibernate poradzi sobie z zapisem danych do odpowiednich tabel? Otóż właśnie po to zostały utworzone tak zwane pliki mapujące. Warto się im dokładnie przyjrzeć. Niestety umieszczenie tych kodów w całości jest bardzo nieczytelne postaram się opisać ich fragmenty.

Plik Works.hbm.xml
- Zdefiniowanie nazwy (name) klasy oraz nazwy tabeli (table)

<class name="przykad1.Works" table="WORKS">


- Klucz wygenerowany przez aplikację. Stworzone jest specjalne pole dla klucza <id> posiada ono takie atrybuty: nazwę(name), czyli jak będzie nazwane to pole w klasie oraz typ(type). W znacznik column określane są własności kolumny tej tabeli . Dodatkowo dołączona jest informacja w jaki sposób ma być generowany klucz. Podstawowe generatory to: native, identity, sequence, assigned.

<id name="id" type="big_decimal">
<column name="ID" precision="22" scale="0" />
<generator class="assigned" />
</id>


- Aby opisać całą tabelę trzeba zdeklarować wszystkie kolumny w tabeli połączone z odpowiednimi polami w klasie, oczywiście trzeba jeszcze określić typy.

<property name="tempo" type="big_decimal">
<column name="TEMPO" precision="22" scale="0" />
</property>


- Element <set> informuje, że dane pole jest typu java.util.Set. W tym przykładzie ma ono nazwę authorses. Ponieważ wystąpiła tu relacja wiele do wielu, wymaga to utworzenia dodatkowej tabeli łączącej, dlatego została określona nazwa tej tabeli AUTHOR_WORK.

<set name="authorses" inverse="false" table="AUTHOR_WORK">
<key>
<column name="WORK_ID" precision="22" scale="0" not-null="true" />
</key>
<many-to-many entity-name="przykad1.Authors">
<column name="AUTHOR_ID" precision="22" scale="0" not-null="true" />
</many-to-many>
</set>


Inne pliki zostały odwzorowane według podobnych schematów. Może jeszcze jeden przykład tym razem relacji jeden do wiele.

Plik: Persons.hmb.xml

<set name="authorses" inverse="true">
<key>
<column name="ID" precision="22" scale="0" not-null="true" unique="true" />
</key>
<one-to-many class="przykad1.Authors" />
</set>

Oraz odzwierciedlenie tej relacji wpliku Authors.hmb.xml

<many-to-one name="persons" class="przykad1.Persons" update="false" insert="false" fetch="select">
<column name="ID" precision="22" scale="0" not-null="true" unique="true" />
</many-to-one>




Odwzorowanie dziedziczenia, asocjacji i kompozycji w bazie


Cel: Stworzenie efektywnego modelu obiektowego przy pomocy Hibernate: dziedziczenie, asocjacja, kompozycja. Wybór strategii odzwierciedlenia dziedziczenia w bazie danych.

Trochę inna strona Hibernate. Do tej pory praca z Hibernate wyglądała następująco: po prawidłowym skonfigurowaniu połączenia z bazą danych należało stworzyć model obiektowy baz danych, a następnie przy pomocy plików mapujących można było wygenerować schemat bazy danych. Jest to tak zwane "podejście z góry w dół".

W NetBeans 6.5 zostało dodane narzędzie, które umożliwia odwrotny scenariusz odwzorowywania, czyli na początku tworzony jest schemat bazy danych, a następnie przy pomocy narzędzi Hibernate zostają wygenerowane klasy Javy oraz pliki odwzorowań. Tak zwane "podejście z dołu do góry".

Jednak problemy odwzorowania relacyjno obiektowego nie znikają. Schemat obiektowy posiada wiele takich własności, których nie można bezpośrednio przełożyć na schemat relacyjny. Problem pojawia się w momencie gdy chcemy odzwierciedlić dziedziczenie, asocjacje czy kompozycję.

1. Dziedziczenie

Istnieją trzy różne podejścia stosowane do odwzorowania dziedziczenia:

1.1. Tabela na każdą klasę konkretną – dokładnie jedna tabela na każdą nieabstrakcyjną klasę, wszystkie własności klasy nadrzędnej są dopisywane do klas dziedziczącej.

WADA: Zapytanie dotyczące klasy bazowej musi zostać rozbite na wiele poleceń SELECT, często jest to mało wydajne.

Wygląda to tak:


1.2. Tabela na każdą hierarchie klas – czyli całą hierarchia klas odwzorowywana jest w jednej tabeli. Dodatkowo dodawana jest kolumna dyskryminatora typu.

WADA: Nie można nadać ograniczenia Not null dla kolumn które są właściwościami podklasy.

1.3. Tabela na każdą podklasę – czyli każda klasa jest reprezentowana jako jedna tabela w bazie i podklasy są w asocjacji z klasą nadrzędną.

WADA: Złożone zapytania.


Wszystkie te modele mają swoje wady i zalety tak więc należy stosować strategię odpowiednią do konkretnego schematu.


Tu omówiony został przykład:
Odwzorowanie dziedziczenia przykład
http://agatkiwoj.blogspot.com/2008/11/odwzrowanie-dziedziczenia-przykad.html