Programowanie wielowarstwowe i komponentowe

Programowanie wielowarstwowe i komponentowe HIBERNATE CD. Rodzaje relacji • Jeden do wielu – Pojedyncza Osoba ma wiele Wpisów • Wiele do jednego ...
Author: Mirosław Dudek
6 downloads 0 Views 619KB Size
Programowanie wielowarstwowe i komponentowe

HIBERNATE CD.

Rodzaje relacji • Jeden do wielu – Pojedyncza Osoba ma wiele Wpisów

• Wiele do jednego – Wiele Wpisów należy do jednej Osoby

• Jeden do jednego – Pojedyncza Osoba ma jeden Adres zameldowania – Pojedynczy Adres zameldowania przynależy do jednej Osoby

• Wiele do wielu – Wiele Studentów ma wiele Przedmiotów – Wiele Przedmiotów przynależy do wielu Studentów

Tworzenie relacji • 1:M/M:1 – Po stronie pojedynczego obiektu mapowana jest kolekcja obiektów (List, Set, Map itp.) •

– Po stronie wielu obiektów, mapowany jest pojedynczy obiekt • • •

Typy kolekcji Hibernate • – Wymaga podania kolumny wartości

• – Wymaga określenia kolumn klucza i wartości

• – Posortowawna, wymaga zaindeksowanej kolumny w tabeli pojedynczego obiektu

• – Mapowanie do zwykłej tablicy, wymaga zaindeksowanej kolumny w tabeli pojedynczego obiektu

• – Podobnie jak lista, ale nie wymaga indeksu

• – Używany do relacji wiele do wielu

Połączenie poprzez • Powiązanie Osoba – Wpis (do bloga) Mapowanie Osoba w klasie Wpis:

Przykład relacji 1:M •

Relacja Osoba-Wpisy (np. do bloga)

public class Osoba { private private private private

int id; String imie; String nazwisko; Set wpisy;

public class Wpis { private int id; private Osoba osoba; private String text;

Przykład relacji 1:M cd. •

Wpis.hbm.cfg



Przykład relacji 1:M cd. •

Osoba.hbm.cfg



Przykład relacji 1:M cd. •

hibernate.cfg.xml

com.mysql.jdbc.Driver passsword jdbc:mysql://localhost/test7 root org.hibernate.dialect.MySQL5Dialect true update

Przykład relacji 1:M cd. public class HibernateUtil {

private static final SessionFactory sessionFactory; private static ServiceRegistry serviceRegistry; static { try { Configuration config = new Configuration().configure();

config.addClass(pl.example.Osoba.class); config.addClass(pl.example.Wpis.class); serviceRegistry = new StandardServiceRegistryBuilder() .applySettings(config.getProperties()).build(); sessionFactory = config.buildSessionFactory(serviceRegistry); } catch (Throwable ex) { System.err.println("Initial SessionFactory creation failed." + ex); throw new ExceptionInInitializerError(ex); } } public static SessionFactory getSessionFactory() { return sessionFactory; } }

Przykład relacji 1:M cd. SessionFactory sf = HibernateUtil.getSessionFactory(); Session session = sf.openSession(); Transaction t = session.beginTransaction(); Osoba o = new Osoba(); o.setImie("Jan"); session.save(o); Wpis w = new Wpis(); w.setText("Hello world!"); w.setOsoba(o); session.save(w); w = new Wpis(); w.setText("Inny tekst…"); w.setOsoba(o); session.save(w); session.flush(); t.commit(); session.close();

Zapytania do bazy danych • Zapytania w języku HQL (Hibernate Query Language) – Język od strony składni wyglądający jak SQL • SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, połączenia, podzapytania (jeśli wykorzystywany SZBD je wspiera)

– W pełni zorientowany obiektowo • dziedziczenie, polimorfizm, asocjacje

• Zapytania w natywnym SQL – Możliwość wykorzystania specyficznych konstrukcji np. CONNECT

• Zapytania poprzez obiekty Criteria – Budowa zapytań poprzez obiektowe API

• Zapytania poprzez obiekty Example – Kryteria zapytania budowane w oparciu o przykładową instancję (QBE – Query By Example)

• Filtry – Aplikowane do kolekcji lub tablic

HQL – list() •

Wykonywanie zapytań poprzez list() –



Zwraca cały wynik zapytania do kolekcji w pamięci (instancje pozostają w stanie trwałym)

Przykład

List wpisy = (List)session.createQuery( "from Wpis w where osoba.id=2").list(); for (Wpis wpis : wpisy) { System.out.println( wpis.getOsoba().getImie() +" napisal " + wpis.getText()); }

List osoby = (List)session.createQuery( "from Osoba where id=11").list(); Set wpisyOsoby = osoby.get(0).getWpisy(); for (Wpis wpis : wpisyOsoby) { System.out.println( wpis.getText() ); }

HQL – iterate() • Wykonywanie zapytań poprzez iterate() – Zwraca wynik w kilku zapytaniach SELECT: • Pobranie identyfikatorów • Oddzielne zapytania pobierające poszczególne instancje

– Może być efektywniejsze od list(), gdy instancje już są w pamięci podręcznej, ale zazwyczaj wolniejsze

Iterator osoby = session.createQuery( "from osoba as os where os.miejscowosc = 'Częstochowa'") .iterate(); while (osoby.hasNext()) { Osoba o = (Osoba) osoby.next(); … }

Przykłady zapytań HQL • • • • •

from pl.example.Osoba from Osoba from java.lang.Object from Osoba where miejscowosc is not null order by naziwisko, imie from Osoba o, Wpis w where o.id = w.osoba.id

• select os.nazwisko from Osoba os where os.naziwsko like ‘K%’ • select sum(zarobki) from Osoba group by stanowisko • select sum(zarobki) from Osoba group by stanowisko having sum(zarobki) > 2000

HQL – Pobieranie obiektów z bazy danych • Domyślnie w przypadku operacji połączenia, HQL nie pobiera natychmiast związanych obiektów i kolekcji – Domyślnie są one pobierane gdy nastąpi do nich pierwsze odwołanie (tryb „lazy”) – HQL ignoruje w tym względzie ewentualne ustawienia podane przy odwzorowaniu – Stanowi to problem, gdy odwołanie do dowiązanego obiektu lub kolekcji nastąpi po zamknięciu sesji, w której wykonano zapytanie – Rozwiązaniem jest zastosowanie klauzul (działają dla list()): • INNER JOIN FETCH - dla pobrania pojedynczych obiektów • LEFT JOIN FETCH – dla pobrania kolekcji

from Osoba as os left join fetch os.wpisy as w from Wpis as w inner join fetch w.osoba

Przetwarzanie wyników zapytań •

Zapytania sparametryzowane (styl ? lub :nazwa)

List depts = (List)session.createQuery( "from Osoba as os where os.miejscowosc = ?" ) .setString(0, "Częstochowa") .list(); •

Paginacja

Query q = session.createQuery("from Osoba as os where os.loc = 'Częstochowa'"); q.setFirstResult(0); q.setMaxResults(2); List depts = q.list(); •

Przewijalne wyniki zapytań – – –

Poprzez rzutowanie do ScrollableResults Wymaga otwartego połączenia z bazą i otwartego kursora Dostępne gdy sterownik JDBC wspiera przewijalne zbiory wynikowe

Query q = session.createQuery("select ... from ..."); ScrollableResults kursor = q.scroll();

Zapytania w Hibernate • Różne możliwości wykonania zapytania w Hibernate – – – – –

Zapytanie przez ID Zapytanie przez kryteria Zapytanie przez przykład Hibernate Query Language (HQL) Zapytania klasycznym SQL przez Hibernate

• Hibernate wykonuje zoptymalizowane zapytania w zależności od rodzaju bazy danych

Zapytanie przez ID • Wyszukuje obiekty po identyfikatorze • Szybkie typ zapytania, ale uzyskiwany jest jedynie pojedynczy obiekt Osoba osoba = (Osoba)session.get( Osoba.class, osobaId);

Zapytanie przez kryteria • Zapytanie jest tworzone przez wiele kryteriów • Wykorzystywane są 4 interfejsy: – org.hibernate.Criteria • Bazowy obiekt dla tego typu wyszukiwania, tworzony przez session • Zawiera wszystkie restrykcje, agregacje, sortowania dla pojedynczego zapytania

– org.hibernate.DetachedCriteria • Podobnie jak Criteria, ale dołączany do sesji i uruchamiany

– org.hibernate.criterion.Criterion • Reprezentuje pojedyncze ograniczenie dla danego zapytania • Odpowiednik where w zapytaniu SQL

– org.hibernate.criterion.Restrictions • Klasa pomocnicza używana do tworzenia obiektów klasy Criterion

org.hibernate.Criteria • Tworzenie poprzez podanie głównej klasy – session.createCriteria(Class); – session.createCriteria(String className);

• Dodanie restrykcji (klauzula where) – addCriterion(Criterion criterion);

• Dodanie asocjacji, dodanie asocjacji jako aliasu – createAlias(String assocjacjonPath, String alias);

• Dodanie sortownia (order by) – addOrder(Order order)

• Rezultaty jako lista – list();

• Rezultat jako pojedynczy obiekt – uniqueResult();

org.hibernate.DetachedCriteria • Nie jest wymagana sesja, aby utworzyć obiekt – DetachedCriteria.forClass(Class); – DetachedCriteria.forClass(String className); • Tworzenie przez statyczne metody

• Metody identyczne jak w Criteria – Za wyjątkiem metod otrzymujących wyniki list() i uniqueResult()

• Do otrzymania wyników niezbędne jest utworzenie obiektu Criteria – getExecutableCriteria(Session);

org.hibernate.criterion.Restrictions • • • • • • • • • • • •

lt(String propertyName, String value); gt(String propertyName, String value); eq(String properyName, String value); ne(String propertyName, String value); like(String propertyName, String value); isEmpty(String propertyName, String value); isNotEmpty(String propertyName, String value); isNull(String propertyName, String value); isNotNull(String propertyName, String value); in(String propertyName, Collection values); allEq(Map propertyNameValues); between(String propertyName, Object lo, Object hi);

Budowanie zapytania Criteria criteria = session.createCriteria(Osoba.class); List osoby = criteria.list(); Criteria criteria = session.createCriteria(Osoba.class) .addOrder(Order.asc("nazwisko")); List osobyPosortowanePoNazwisku = criteria.list();

Wyszukiwanie pojedynczych obiektów Criteria criteria = session.createCriteria(Osoba.class); Criterion restrictByEmail = Restrictions.eq("email", "[email protected]"); cirteria.add(restrictByEmail); Osoba osoba = (Osoba)criteria.uniqueResult(); Inaczej: Osoba osoba = (Osoba)session .createCriteria(Osoba.class) .add(Restriction. eq("email", "[email protected]") ) .uniqueResult();

Inne przykłady List osoby = session.createCriteria(Osoba.class) .add( Restrictions.between("zarobki",1000, 5000) ) .list();

List osoby = session.createCriteria(Osoba.class) .add( Restrictions.like("nazwisko","K%").ignoreCase() ) .add( Restrictions.like("imie","J%").ignoreCase() ) .list();

OR i AND List osoby = session.createCriteria(Osoba.class) .add(Restrictions.or( Restrictions.and( Restrictions.like("nazwisko","K%"), Restrictions.like("imie","J%") ), Restrictions.like("email", "%gmail.com") ) ) .list()

Użycie DetachedCriteria DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Osoba.class) .add(Restrictions.ilike("nazwisko","K%")); Session session = HibernateUtil.getSessionFactory().getCurrentSession(); Criteria criteria = detachedCriteria.getExecutableCriteria(session); List accountOwners = regularCriteria.list(); Lub: List accountOwners = detachedCriteria.getExecutableCriteria(session) .list();

Zapytanie przez przykład • Zapytanie przez przykład polega na przygotowaniu przykładowego obiektu i na jego podstawie wygenerowania zapytania do bazy danych • Klasa org.hibernate.criterion.Example – Obiekt tworzony przez create(Object obj)

Zapytanie przez przykład Osoba osoba = new Osoba(); osoba.setNazwisko("Kowalski"); Example osobaPrzyklad = Example.create(osoba); List osoby = session.createCriteria(Osoba.class) .add(osobaPrzyklad) .list();

Ustawienie obiektu-przykładu • Domyślnie ignorowane pola: – Identyfikator – Asocjacje – Wartości null

• Dodatkowe ustawienia: – enableLike(MatchMode mode) • Włączenie like do wszystkich String-ów

– ignoreCase() – excludeZeroes(); • Wyłącznie zer

– excludeProperty(String name); • Wyłączenie konkretnej właściwości

– excludeNone(); • Nie wyłączaj zer i null-i

Dziedziczenie • Dziedziczenie w Javie: – extends lub implements

• Problem z dziedziczeniem w relacyjnej bazie danych • Hibernate – cztery sposoby na dziedziczenie – – – –

Bez dziedziczenia Tabela dla konkretnej klasy Tabela dla hierarchii klas Tabela dla subklasy

Bez dziedziczenia • Jedna tabela jest przeznaczona dla konkretnej klasy – Mapowanie zawiera wszystkie pola, nawet wspólne dla innych klas

• Oddzielne pliki mapowania dla każdej z klas

Bez dziedziczenia • KontoROR.java public class KontoROR extends Konto { private int kontoRorId; private String dostep; private double saldo; private Date dataUtworzenia; • KontoOszczednosciowe.java public class KontoOszczednosciowe extends Konto { private int kontoOszczednoscioweId; private double procent; private double saldo; private Date dataUtworzenia;

Bez dziedziczenia

Bez dziedziczenia

Tabela na klasę • Jedna tabela na klasę • Zapis w jednym pliku mapowania – Bazowanie na superklasie – Definicje

Tabela na klasę • Konto.java

public class Konto { private int kontoId; private double saldo; private Date dataUtworzenia; • KontoROR.java public class KontoROR extends Konto { private String dostep; • KontoOszczednosciowe.java public class KontoOszczednosciowe extends Konto { private double procent;

Tabela na klasę

Przykład session = sf.openSession(); t = session.beginTransaction(); KontoOszczednosciowe k1 = new KontoOszczednosciowe(); k1.setDataUtworzenia(new Date()); k1.setProcent(10); session.save(k1); KontoROR k2 = new KontoROR(); k2.setDataUtworzenia(new Date()); k2.setDostep("OK"); session.save(k2); t.commit(); session.close();

Tabela na hierarchię klas • Jedna tabela dla wszystkich subklas • Tabela posiada kolumny dla wszystkich możliwych pól • Plik mapowania – Pojedynczy plik mapowania – Definicja – Używana kolumna, wskazująca na typ klasy



Tabela na subklasę • Jedna tabela dla superklasy i po jednej dla każdej z subklas – Kolumny są współdzielone w tabeli superklasy – Tabele subklas zawierają charakterystyczne dla nich klumny

• Mapowane klas – Pojedynczy plik mapowania bazujący na superklasie – Polecenie

Tabela na subklasę

Tabela na subklasę